diff --git a/README.md b/README.md index c413fd6..cfee50f 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ jSquash name is inspired by jQuery and Squoosh. It symbolizes the browser suppor - [@jSquash/avif](/packages/avif) - An encoder and decoder for AVIF images using the [libavif](https://github.com/AOMediaCodec/libavif) library - [@jSquash/jpeg](/packages/jpeg) - An encoder and decoder for JPEG images using the [MozJPEG](https://github.com/mozilla/mozjpeg) library +- [@jSquash/jxr](/packages/jxr) - A decoder for JPEG XR images using the [jxrlib](https://github.com/bvibber/jpegxr) library - [@jSquash/jxl](/packages/jxl) - An encoder and decoder for JPEG XL images using the [libjxl](https://github.com/libjxl/libjxl) library - [@jSquash/oxipng](/packages/oxipng) - A PNG image optimiser using [Oxipng](https://github.com/shssoichiro/oxipng) - [@jSquash/png](/packages/png) - An encoder and decoder for PNG images using the [rust PNG crate](https://docs.rs/png/0.11.0/png/) diff --git a/examples/jxr-decoder/index.html b/examples/jxr-decoder/index.html new file mode 100644 index 0000000..83c47bc --- /dev/null +++ b/examples/jxr-decoder/index.html @@ -0,0 +1,477 @@ + + + + + + + jSquash JPEG XR Decoder Demo + + + +
+
+

Browser Demo

+

JPEG XR decode in the browser.

+

+ This page loads the committed @jsquash/jxr codec directly from the repository and decodes a + JPEG XR file to ImageData on the client side. Pick a local .jxr, .wdp, + or .hdp file, or pass ?src=/path/to/file.jxr when serving this repo over HTTP. +

+

+ The current decoder path also handles common HDR JPEG XR screenshots, so the preview you see here is the + browser-renderable SDR ImageData output from the wasm codec. +

+
+ +
+ + +
+
+ +

+ Serve this repo over HTTP, then open this page and decode a JPEG XR image. The decoded pixels will be + painted here using CanvasRenderingContext2D.putImageData(). +

+
+
+
+
+ + + + diff --git a/packages/jxr/.npmignore b/packages/jxr/.npmignore new file mode 100644 index 0000000..9d32211 --- /dev/null +++ b/packages/jxr/.npmignore @@ -0,0 +1,6 @@ +*.cpp +Makefile +node_modules +codec/*package.json +*.d.ts.map +tsconfig.tsbuildinfo diff --git a/packages/jxr/README.md b/packages/jxr/README.md new file mode 100644 index 0000000..b741340 --- /dev/null +++ b/packages/jxr/README.md @@ -0,0 +1,57 @@ +# @jsquash/jxr + +[![npm version](https://badge.fury.io/js/@jsquash%2Fjxr.svg)](https://badge.fury.io/js/@jsquash%2Fjxr) + +An easy way to decode JPEG XR images in the browser with WebAssembly. + +Uses the [`jxrlib`](https://github.com/bvibber/jpegxr) library. + +A [jSquash](https://github.com/jamsinclair/jSquash) package. + +## Installation + +```shell +npm install --save @jsquash/jxr +``` + +## Usage + +Note: You will need to either manually include the wasm files from the codec directory or use a bundler like WebPack or Rollup to include them in your app/server. + +### `decode(data: ArrayBuffer): Promise` + +Decodes JPEG XR binary data to `ImageData`. + +#### Example + +```js +import { decode } from '@jsquash/jxr'; + +const imageBuffer = await fetch('/example.jxr').then((res) => res.arrayBuffer()); +const imageData = await decode(imageBuffer); +``` + +## Manual WASM initialisation (not recommended) + +The `decode` module exports an `init` function that can be used to manually load the wasm module. + +```js +import decode, { init as initJXRDecode } from '@jsquash/jxr/decode'; + +initJXRDecode(WASM_MODULE); +const image = await fetch('./image.jxr').then((res) => res.arrayBuffer()).then(decode); +``` + +You can also pass custom options to the `init` function to customise the behaviour of the module. See the [Emscripten documentation](https://emscripten.org/docs/api_reference/module.html#Module) for more information. + +```js +import decode, { init as initJXRDecode } from '@jsquash/jxr/decode'; + +initJXRDecode(null, { + locateFile: (path, prefix) => `https://example.com/${prefix}/${path}`, +}); +``` + +## Known Issues + +See [jSquash Project README](https://github.com/jamsinclair/jSquash#known-issues) diff --git a/packages/jxr/codec/Makefile b/packages/jxr/codec/Makefile new file mode 100644 index 0000000..f130719 --- /dev/null +++ b/packages/jxr/codec/Makefile @@ -0,0 +1,111 @@ +CODEC_URL = https://github.com/bvibber/jpegxr/archive/refs/tags/0.3.1.tar.gz +CODEC_PACKAGE = node_modules/jpegxr.tar.gz +CODEC_DIR = node_modules/jpegxr +JXRLIB_DIR = $(CODEC_DIR)/jxrlib +EXTRACTED_STAMP = $(CODEC_DIR)/.extracted + +ENVIRONMENT = web,worker +PRE_JS = pre.js + +OUT_DEC_JS = dec/jxr_dec.js +OUT_DEC_CPP = dec/jxr_dec.cpp +OUT_DEC_WASM = dec/jxr_dec.wasm + +TOTAL_STACK = 5242880 +INITIAL_MEMORY_SIZE = 16777216 + +CODEC_SOURCES = \ + $(JXRLIB_DIR)/image/sys/adapthuff.c \ + $(JXRLIB_DIR)/image/sys/image.c \ + $(JXRLIB_DIR)/image/sys/strcodec.c \ + $(JXRLIB_DIR)/image/sys/strPredQuant.c \ + $(JXRLIB_DIR)/image/sys/strTransform.c \ + $(JXRLIB_DIR)/image/sys/perfTimerANSI.c \ + $(JXRLIB_DIR)/image/decode/decode.c \ + $(JXRLIB_DIR)/image/decode/postprocess.c \ + $(JXRLIB_DIR)/image/decode/segdec.c \ + $(JXRLIB_DIR)/image/decode/strdec.c \ + $(JXRLIB_DIR)/image/decode/strInvTransform.c \ + $(JXRLIB_DIR)/image/decode/strPredQuantDec.c \ + $(JXRLIB_DIR)/image/decode/JXRTranscode.c \ + $(JXRLIB_DIR)/jxrgluelib/JXRGlue.c \ + $(JXRLIB_DIR)/jxrgluelib/JXRGlueJxr.c \ + $(JXRLIB_DIR)/jxrgluelib/JXRGluePFC.c \ + $(JXRLIB_DIR)/jxrgluelib/JXRMeta.c + +CODEC_OBJECTS = $(CODEC_SOURCES:.c=.o) +WRAPPER_OBJECT = $(OUT_DEC_CPP:.cpp=.o) + +JXR_INCLUDE_FLAGS = \ + -D__ANSI__ \ + -DDISABLE_PERF_MEASUREMENT \ + -I $(JXRLIB_DIR)/jxrgluelib \ + -I $(JXRLIB_DIR)/common/include \ + -I $(JXRLIB_DIR)/image/sys \ + -Wno-constant-conversion \ + -Wno-unused-const-variable \ + -Wno-deprecated-declarations \ + -Wno-comment \ + -Wno-unused-value \ + -Wno-unused-function \ + -Wno-unknown-pragmas \ + -Wno-extra-tokens \ + -Wno-missing-field-initializers \ + -Wno-shift-negative-value \ + -Wno-dangling-else \ + -Wno-sign-compare \ + -Wno-strict-aliasing \ + -Wno-implicit-fallthrough \ + -Wno-endif-labels \ + -Wno-parentheses \ + -Wno-misleading-indentation \ + -Wno-unused-but-set-variable + +.PHONY: all clean + +all: $(OUT_DEC_JS) + +$(OUT_DEC_JS): $(WRAPPER_OBJECT) $(CODEC_OBJECTS) + $(CXX) \ + $(LDFLAGS) \ + -O0 \ + --pre-js $(PRE_JS) \ + --bind \ + -s ENVIRONMENT=$(ENVIRONMENT) \ + -s EXPORT_ES6=1 \ + -s DYNAMIC_EXECUTION=0 \ + -s ALLOW_MEMORY_GROWTH=1 \ + -s MODULARIZE=1 \ + -s TOTAL_STACK=$(TOTAL_STACK) \ + -s INITIAL_MEMORY=$(INITIAL_MEMORY_SIZE) \ + -o $@ \ + $(WRAPPER_OBJECT) $(CODEC_OBJECTS) + +$(OUT_DEC_JS): $(EXTRACTED_STAMP) + +$(CODEC_OBJECTS): %.o: $(EXTRACTED_STAMP) + $(CC) -c \ + $(CFLAGS) \ + $(JXR_INCLUDE_FLAGS) \ + -o $@ \ + $(@:.o=.c) + +$(WRAPPER_OBJECT): %.o: %.cpp $(EXTRACTED_STAMP) + $(CXX) -c \ + $(CXXFLAGS) \ + $(JXR_INCLUDE_FLAGS) \ + -o $@ \ + $< + +$(EXTRACTED_STAMP): $(CODEC_PACKAGE) + mkdir -p $(CODEC_DIR) + tar xzm --strip 1 -C $(CODEC_DIR) -f $(CODEC_PACKAGE) + touch $@ + +$(CODEC_PACKAGE): + mkdir -p $(@D) + curl -sL $(CODEC_URL) -o $@ + +clean: + $(RM) $(WRAPPER_OBJECT) $(OUT_DEC_JS) $(OUT_DEC_WASM) + $(RM) $(CODEC_OBJECTS) diff --git a/packages/jxr/codec/dec/jxr_dec.cpp b/packages/jxr/codec/dec/jxr_dec.cpp new file mode 100644 index 0000000..3517d5c --- /dev/null +++ b/packages/jxr/codec/dec/jxr_dec.cpp @@ -0,0 +1,948 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "JXRGlue.h" + +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +using namespace emscripten; + +thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray"); +thread_local const val ImageData = val::global("ImageData"); + +namespace { +enum class OutputKind { + RGBA8, + PRGBA8, + BGRA8, + PBGRA8, + RGB8, + BGR8, + RGBX8, + BGRX8, + GRAY8, + RGBA16, + PRGBA16, + RGB16, + RGB16X, + GRAY16, + RGBAFloat, + PRGBAFloat, + RGBFloat, + RGBFloatX, + GRAYFloat, + RGBAHalf, + RGBHalf, + RGBHalfX, + GRAYHalf, + RGBAFixed16, + RGBFixed16, + RGBFixed16X, + GRAYFixed16, + RGBAFixed32, + RGBFixed32, + RGBFixed32X, + GRAYFixed32, + RGB101010, + RGBE, +}; + +struct DecodeTarget { + PKPixelFormatGUID guid; + OutputKind kind; + int bytes_per_pixel; +}; + +struct ToneMapSettings { + bool enabled; + float white; +}; + +constexpr size_t kToneMapSampleCount = 16384; +constexpr float kToneMapWhitePercentile = 0.99f; + +const DecodeTarget kTargets[] = { + {GUID_PKPixelFormat32bppRGBA, OutputKind::RGBA8, 4}, + {GUID_PKPixelFormat32bppPRGBA, OutputKind::PRGBA8, 4}, + {GUID_PKPixelFormat32bppBGRA, OutputKind::BGRA8, 4}, + {GUID_PKPixelFormat32bppPBGRA, OutputKind::PBGRA8, 4}, + {GUID_PKPixelFormat24bppRGB, OutputKind::RGB8, 3}, + {GUID_PKPixelFormat24bppBGR, OutputKind::BGR8, 3}, + {GUID_PKPixelFormat32bppRGB, OutputKind::RGBX8, 4}, + {GUID_PKPixelFormat32bppBGR, OutputKind::BGRX8, 4}, + {GUID_PKPixelFormat8bppGray, OutputKind::GRAY8, 1}, + {GUID_PKPixelFormat64bppRGBA, OutputKind::RGBA16, 8}, + {GUID_PKPixelFormat64bppPRGBA, OutputKind::PRGBA16, 8}, + {GUID_PKPixelFormat48bppRGB, OutputKind::RGB16, 6}, + {GUID_PKPixelFormat64bppRGBFixedPoint, OutputKind::RGBFixed16X, 8}, + {GUID_PKPixelFormat16bppGray, OutputKind::GRAY16, 2}, + {GUID_PKPixelFormat128bppRGBAFloat, OutputKind::RGBAFloat, 16}, + {GUID_PKPixelFormat128bppPRGBAFloat, OutputKind::PRGBAFloat, 16}, + {GUID_PKPixelFormat96bppRGBFloat, OutputKind::RGBFloat, 12}, + {GUID_PKPixelFormat128bppRGBFloat, OutputKind::RGBFloatX, 16}, + {GUID_PKPixelFormat32bppGrayFloat, OutputKind::GRAYFloat, 4}, + {GUID_PKPixelFormat64bppRGBAHalf, OutputKind::RGBAHalf, 8}, + {GUID_PKPixelFormat48bppRGBHalf, OutputKind::RGBHalf, 6}, + {GUID_PKPixelFormat64bppRGBHalf, OutputKind::RGBHalfX, 8}, + {GUID_PKPixelFormat16bppGrayHalf, OutputKind::GRAYHalf, 2}, + {GUID_PKPixelFormat64bppRGBAFixedPoint, OutputKind::RGBAFixed16, 8}, + {GUID_PKPixelFormat48bppRGBFixedPoint, OutputKind::RGBFixed16, 6}, + {GUID_PKPixelFormat16bppGrayFixedPoint, OutputKind::GRAYFixed16, 2}, + {GUID_PKPixelFormat128bppRGBAFixedPoint, OutputKind::RGBAFixed32, 16}, + {GUID_PKPixelFormat96bppRGBFixedPoint, OutputKind::RGBFixed32, 12}, + {GUID_PKPixelFormat128bppRGBFixedPoint, OutputKind::RGBFixed32X, 16}, + {GUID_PKPixelFormat32bppGrayFixedPoint, OutputKind::GRAYFixed32, 4}, + {GUID_PKPixelFormat32bppRGB101010, OutputKind::RGB101010, 4}, + {GUID_PKPixelFormat32bppRGBE, OutputKind::RGBE, 4}, +}; + +const DecodeTarget* find_decode_target(const PKPixelFormatGUID& guid) { + for (const DecodeTarget& candidate : kTargets) { + if (IsEqualGUID(candidate.guid, guid)) { + return &candidate; + } + } + + return nullptr; +} + +bool is_hdr_linear_target(OutputKind kind) { + switch (kind) { + case OutputKind::RGBAFloat: + case OutputKind::PRGBAFloat: + case OutputKind::RGBFloat: + case OutputKind::RGBFloatX: + case OutputKind::GRAYFloat: + case OutputKind::RGBAHalf: + case OutputKind::RGBHalf: + case OutputKind::RGBHalfX: + case OutputKind::GRAYHalf: + case OutputKind::RGBAFixed16: + case OutputKind::RGBFixed16: + case OutputKind::RGBFixed16X: + case OutputKind::GRAYFixed16: + case OutputKind::RGBAFixed32: + case OutputKind::RGBFixed32: + case OutputKind::RGBFixed32X: + case OutputKind::GRAYFixed32: + return true; + default: + return false; + } +} + +bool is_alpha_target(OutputKind kind) { + switch (kind) { + case OutputKind::RGBA8: + case OutputKind::PRGBA8: + case OutputKind::BGRA8: + case OutputKind::PBGRA8: + case OutputKind::RGBA16: + case OutputKind::PRGBA16: + case OutputKind::RGBAFloat: + case OutputKind::PRGBAFloat: + case OutputKind::RGBAHalf: + case OutputKind::RGBAFixed16: + case OutputKind::RGBAFixed32: + return true; + default: + return false; + } +} + +uint8_t unpremultiply_channel(uint8_t value, uint8_t alpha) { + if (alpha == 0) { + return 0; + } + + const int scaled = (static_cast(value) * 255 + alpha / 2) / alpha; + return static_cast(std::min(scaled, 255)); +} + +uint16_t unpremultiply_channel_16(uint16_t value, uint16_t alpha) { + if (alpha == 0) { + return 0; + } + + const uint32_t scaled = + (static_cast(value) * 65535u + alpha / 2u) / alpha; + return static_cast(std::min(scaled, 65535u)); +} + +float unpremultiply_channel_float(float value, float alpha) { + if (alpha <= 0.0f) { + return 0.0f; + } + + return value / alpha; +} + +template +T read_value(const uint8_t* ptr) { + T value; + std::memcpy(&value, ptr, sizeof(T)); + return value; +} + +float bitcast_float(uint32_t bits) { + float value; + std::memcpy(&value, &bits, sizeof(value)); + return value; +} + +float convert_half_to_float(uint16_t value) { + const uint32_t sign = (value >> 15) & 0x0001; + const uint32_t exponent = (value >> 10) & 0x001f; + const uint32_t mantissa = value & 0x03ff; + + if (exponent == 0) { + return bitcast_float(sign << 31); + } + + if (exponent == 0x1f) { + return bitcast_float((sign << 31) | (0xffu << 23) | (mantissa << 13)); + } + + return bitcast_float( + (sign << 31) | ((exponent - 15 + 127) << 23) | (mantissa << 13)); +} + +uint8_t convert_float_to_u8(float value) { + if (value <= 0.0f) { + return 0; + } + + if (value <= 0.0031308f) { + return static_cast((255.0f * value * 12.92f) + 0.5f); + } + + if (value < 1.0f) { + return static_cast( + (255.0f * ((1.055f * std::pow(value, 1.0f / 2.4f)) - 0.055f)) + + 0.5f); + } + + return 255; +} + +uint8_t convert_alpha_float_to_u8(float value) { + if (value <= 0.0f) { + return 0; + } + + if (value < 1.0f) { + return static_cast((255.0f * value) + 0.5f); + } + + return 255; +} + +float fixed16_to_float(int16_t value) { + return static_cast(value) * (1.0f / static_cast(1 << 13)); +} + +float fixed32_to_float(int32_t value) { + return static_cast(value) * (1.0f / static_cast(1 << 24)); +} + +float luma_rgb(float r, float g, float b) { + return r * 0.2126f + g * 0.7152f + b * 0.0722f; +} + +void scale_rgb(float& r, float& g, float& b, float luma_out) { + const float luma_in = luma_rgb(r, g, b); + if (luma_in <= 0.0f) { + r = 0.0f; + g = 0.0f; + b = 0.0f; + return; + } + + const float scale = luma_out / luma_in; + r *= scale; + g *= scale; + b *= scale; +} + +void tone_map_reinhard_luma( + float& r, + float& g, + float& b, + const ToneMapSettings& settings) { + r = std::max(r, 0.0f); + g = std::max(g, 0.0f); + b = std::max(b, 0.0f); + + if (!settings.enabled) { + return; + } + + const float white = std::max(settings.white, 1.0f); + const float white2 = white * white; + const float luma_in = luma_rgb(r, g, b); + const float luma_out = + luma_in * (1.0f + luma_in / white2) / (1.0f + luma_in); + scale_rgb(r, g, b, luma_out); +} + +void read_linear_rgb( + const uint8_t* pixel, + const DecodeTarget& target, + float& r, + float& g, + float& b) { + switch (target.kind) { + case OutputKind::RGBAFloat: + r = read_value(pixel + 0); + g = read_value(pixel + 4); + b = read_value(pixel + 8); + return; + case OutputKind::PRGBAFloat: { + const float alpha = read_value(pixel + 12); + r = unpremultiply_channel_float(read_value(pixel + 0), alpha); + g = unpremultiply_channel_float(read_value(pixel + 4), alpha); + b = unpremultiply_channel_float(read_value(pixel + 8), alpha); + return; + } + case OutputKind::RGBFloat: + case OutputKind::RGBFloatX: + r = read_value(pixel + 0); + g = read_value(pixel + 4); + b = read_value(pixel + 8); + return; + case OutputKind::GRAYFloat: + r = g = b = read_value(pixel); + return; + case OutputKind::RGBAHalf: + r = convert_half_to_float(read_value(pixel + 0)); + g = convert_half_to_float(read_value(pixel + 2)); + b = convert_half_to_float(read_value(pixel + 4)); + return; + case OutputKind::RGBHalf: + case OutputKind::RGBHalfX: + r = convert_half_to_float(read_value(pixel + 0)); + g = convert_half_to_float(read_value(pixel + 2)); + b = convert_half_to_float(read_value(pixel + 4)); + return; + case OutputKind::GRAYHalf: + r = g = b = convert_half_to_float(read_value(pixel)); + return; + case OutputKind::RGBAFixed16: + r = fixed16_to_float(read_value(pixel + 0)); + g = fixed16_to_float(read_value(pixel + 2)); + b = fixed16_to_float(read_value(pixel + 4)); + return; + case OutputKind::RGBFixed16: + case OutputKind::RGBFixed16X: + r = fixed16_to_float(read_value(pixel + 0)); + g = fixed16_to_float(read_value(pixel + 2)); + b = fixed16_to_float(read_value(pixel + 4)); + return; + case OutputKind::GRAYFixed16: + r = g = b = fixed16_to_float(read_value(pixel)); + return; + case OutputKind::RGBAFixed32: + r = fixed32_to_float(read_value(pixel + 0)); + g = fixed32_to_float(read_value(pixel + 4)); + b = fixed32_to_float(read_value(pixel + 8)); + return; + case OutputKind::RGBFixed32: + case OutputKind::RGBFixed32X: + r = fixed32_to_float(read_value(pixel + 0)); + g = fixed32_to_float(read_value(pixel + 4)); + b = fixed32_to_float(read_value(pixel + 8)); + return; + case OutputKind::GRAYFixed32: + r = g = b = fixed32_to_float(read_value(pixel)); + return; + default: + r = 0.0f; + g = 0.0f; + b = 0.0f; + return; + } +} + +float read_alpha_sample(const uint8_t* pixel, const DecodeTarget& target) { + switch (target.kind) { + case OutputKind::RGBA8: + case OutputKind::PRGBA8: + case OutputKind::BGRA8: + case OutputKind::PBGRA8: + return static_cast(pixel[3]) * (1.0f / 255.0f); + case OutputKind::RGBA16: + case OutputKind::PRGBA16: + return static_cast(read_value(pixel + 6)) * + (1.0f / 65535.0f); + case OutputKind::RGBAFloat: + case OutputKind::PRGBAFloat: + return read_value(pixel + 12); + case OutputKind::RGBAHalf: + return convert_half_to_float(read_value(pixel + 6)); + case OutputKind::RGBAFixed16: + return fixed16_to_float(read_value(pixel + 6)); + case OutputKind::RGBAFixed32: + return fixed32_to_float(read_value(pixel + 12)); + default: + return 1.0f; + } +} + +bool should_preserve_alpha( + const uint8_t* decoded_pixels, + size_t pixel_count, + const DecodeTarget& target, + bool has_alpha) { + if (!has_alpha || !is_alpha_target(target.kind)) { + return false; + } + + if (!is_hdr_linear_target(target.kind) || pixel_count == 0) { + return true; + } + + const size_t sample_stride = + std::max(1, pixel_count / kToneMapSampleCount); + for (size_t i = 0; i < pixel_count; i += sample_stride) { + const float alpha = read_alpha_sample( + decoded_pixels + (i * target.bytes_per_pixel), target); + if (std::isfinite(alpha) && alpha > 0.000001f) { + return true; + } + } + + return false; +} + +void assign_rgba( + std::vector& rgba_pixels, + size_t offset, + uint8_t r, + uint8_t g, + uint8_t b, + uint8_t a) { + rgba_pixels[offset + 0] = r; + rgba_pixels[offset + 1] = g; + rgba_pixels[offset + 2] = b; + rgba_pixels[offset + 3] = a; +} + +void assign_rgba( + uint8_t* rgba_pixels, + size_t offset, + uint8_t r, + uint8_t g, + uint8_t b, + uint8_t a) { + rgba_pixels[offset + 0] = r; + rgba_pixels[offset + 1] = g; + rgba_pixels[offset + 2] = b; + rgba_pixels[offset + 3] = a; +} + +void assign_linear_rgba( + uint8_t* rgba_pixels, + size_t offset, + float r, + float g, + float b, + float a, + bool has_alpha, + const ToneMapSettings& tone_map) { + tone_map_reinhard_luma(r, g, b, tone_map); + if (!has_alpha) { + a = 1.0f; + } + assign_rgba( + rgba_pixels, offset, + convert_float_to_u8(r), + convert_float_to_u8(g), + convert_float_to_u8(b), + convert_alpha_float_to_u8(a)); +} + +val create_image_data(const std::vector& rgba, int width, int height) { + return ImageData.new_( + Uint8ClampedArray.new_(typed_memory_view(rgba.size(), rgba.data())), + width, height); +} + +ToneMapSettings compute_tone_map_settings( + const uint8_t* decoded_pixels, + size_t pixel_count, + const DecodeTarget& target) { + if (!is_hdr_linear_target(target.kind) || pixel_count == 0) { + return {false, 1.0f}; + } + + const size_t sample_stride = + std::max(1, pixel_count / kToneMapSampleCount); + std::vector luminance_samples; + luminance_samples.reserve((pixel_count + sample_stride - 1) / sample_stride); + + float max_channel = 0.0f; + for (size_t i = 0; i < pixel_count; i += sample_stride) { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + read_linear_rgb( + decoded_pixels + (i * target.bytes_per_pixel), target, r, g, b); + r = std::max(r, 0.0f); + g = std::max(g, 0.0f); + b = std::max(b, 0.0f); + max_channel = std::max(max_channel, std::max(r, std::max(g, b))); + luminance_samples.push_back(luma_rgb(r, g, b)); + } + + if (luminance_samples.empty()) { + return {false, 1.0f}; + } + + std::sort(luminance_samples.begin(), luminance_samples.end()); + const size_t white_index = static_cast( + (luminance_samples.size() - 1) * kToneMapWhitePercentile); + const float white = luminance_samples[white_index]; + + if ((!std::isfinite(white) || white <= 1.0f) && max_channel <= 1.0f) { + return {false, 1.0f}; + } + + return {true, std::max(white, 1.0f)}; +} + +void convert_decoded_pixels_to_rgba( + const uint8_t* decoded_pixels, + size_t pixel_count, + const DecodeTarget& target, + bool has_alpha, + uint8_t* rgba_pixels) { + const ToneMapSettings tone_map = + compute_tone_map_settings(decoded_pixels, pixel_count, target); + const bool use_alpha = + should_preserve_alpha(decoded_pixels, pixel_count, target, has_alpha); + + for (size_t i = 0; i < pixel_count; ++i) { + const uint8_t* pixel = decoded_pixels + (i * target.bytes_per_pixel); + const size_t dst = i * 4; + + switch (target.kind) { + case OutputKind::RGBA8: + rgba_pixels[dst + 0] = pixel[0]; + rgba_pixels[dst + 1] = pixel[1]; + rgba_pixels[dst + 2] = pixel[2]; + rgba_pixels[dst + 3] = use_alpha ? pixel[3] : 255; + break; + case OutputKind::PRGBA8: { + const uint8_t alpha = use_alpha ? pixel[3] : 255; + assign_rgba( + rgba_pixels, dst, + unpremultiply_channel(pixel[0], alpha), + unpremultiply_channel(pixel[1], alpha), + unpremultiply_channel(pixel[2], alpha), + alpha); + break; + } + case OutputKind::BGRA8: + assign_rgba( + rgba_pixels, dst, pixel[2], pixel[1], pixel[0], use_alpha ? pixel[3] : 255); + break; + case OutputKind::PBGRA8: { + const uint8_t alpha = use_alpha ? pixel[3] : 255; + assign_rgba( + rgba_pixels, dst, + unpremultiply_channel(pixel[2], alpha), + unpremultiply_channel(pixel[1], alpha), + unpremultiply_channel(pixel[0], alpha), + alpha); + break; + } + case OutputKind::RGB8: + assign_rgba(rgba_pixels, dst, pixel[0], pixel[1], pixel[2], 255); + break; + case OutputKind::BGR8: + assign_rgba(rgba_pixels, dst, pixel[2], pixel[1], pixel[0], 255); + break; + case OutputKind::RGBX8: + assign_rgba(rgba_pixels, dst, pixel[0], pixel[1], pixel[2], 255); + break; + case OutputKind::BGRX8: + assign_rgba(rgba_pixels, dst, pixel[2], pixel[1], pixel[0], 255); + break; + case OutputKind::GRAY8: + assign_rgba(rgba_pixels, dst, pixel[0], pixel[0], pixel[0], 255); + break; + case OutputKind::RGBA16: + assign_rgba( + rgba_pixels, dst, + read_value(pixel + 0) >> 8, + read_value(pixel + 2) >> 8, + read_value(pixel + 4) >> 8, + use_alpha ? (read_value(pixel + 6) >> 8) : 255); + break; + case OutputKind::PRGBA16: { + const uint16_t alpha = use_alpha ? read_value(pixel + 6) : 65535u; + assign_rgba( + rgba_pixels, dst, + unpremultiply_channel_16(read_value(pixel + 0), alpha) >> 8, + unpremultiply_channel_16(read_value(pixel + 2), alpha) >> 8, + unpremultiply_channel_16(read_value(pixel + 4), alpha) >> 8, + alpha >> 8); + break; + } + case OutputKind::RGB16: + assign_rgba( + rgba_pixels, dst, + read_value(pixel + 0) >> 8, + read_value(pixel + 2) >> 8, + read_value(pixel + 4) >> 8, + 255); + break; + case OutputKind::RGB16X: + assign_rgba( + rgba_pixels, dst, + read_value(pixel + 0) >> 8, + read_value(pixel + 2) >> 8, + read_value(pixel + 4) >> 8, + 255); + break; + case OutputKind::GRAY16: { + const uint8_t gray = read_value(pixel) >> 8; + assign_rgba(rgba_pixels, dst, gray, gray, gray, 255); + break; + } + case OutputKind::RGBAFloat: { + assign_linear_rgba( + rgba_pixels, + dst, + read_value(pixel + 0), + read_value(pixel + 4), + read_value(pixel + 8), + read_value(pixel + 12), + use_alpha, + tone_map); + break; + } + case OutputKind::PRGBAFloat: { + const float alpha = use_alpha ? read_value(pixel + 12) : 1.0f; + assign_linear_rgba( + rgba_pixels, + dst, + unpremultiply_channel_float(read_value(pixel + 0), alpha), + unpremultiply_channel_float(read_value(pixel + 4), alpha), + unpremultiply_channel_float(read_value(pixel + 8), alpha), + alpha, + use_alpha, + tone_map); + break; + } + case OutputKind::RGBFloat: + assign_linear_rgba( + rgba_pixels, + dst, + read_value(pixel + 0), + read_value(pixel + 4), + read_value(pixel + 8), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::RGBFloatX: + assign_linear_rgba( + rgba_pixels, + dst, + read_value(pixel + 0), + read_value(pixel + 4), + read_value(pixel + 8), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::GRAYFloat: { + const float gray = read_value(pixel); + assign_linear_rgba( + rgba_pixels, dst, gray, gray, gray, 1.0f, use_alpha, tone_map); + break; + } + case OutputKind::RGBAHalf: + assign_linear_rgba( + rgba_pixels, + dst, + convert_half_to_float(read_value(pixel + 0)), + convert_half_to_float(read_value(pixel + 2)), + convert_half_to_float(read_value(pixel + 4)), + convert_half_to_float(read_value(pixel + 6)), + use_alpha, + tone_map); + break; + case OutputKind::RGBHalf: + assign_linear_rgba( + rgba_pixels, + dst, + convert_half_to_float(read_value(pixel + 0)), + convert_half_to_float(read_value(pixel + 2)), + convert_half_to_float(read_value(pixel + 4)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::RGBHalfX: + assign_linear_rgba( + rgba_pixels, + dst, + convert_half_to_float(read_value(pixel + 0)), + convert_half_to_float(read_value(pixel + 2)), + convert_half_to_float(read_value(pixel + 4)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::GRAYHalf: { + const float gray = + convert_half_to_float(read_value(pixel)); + assign_linear_rgba( + rgba_pixels, dst, gray, gray, gray, 1.0f, use_alpha, tone_map); + break; + } + case OutputKind::RGBAFixed16: + assign_linear_rgba( + rgba_pixels, + dst, + fixed16_to_float(read_value(pixel + 0)), + fixed16_to_float(read_value(pixel + 2)), + fixed16_to_float(read_value(pixel + 4)), + fixed16_to_float(read_value(pixel + 6)), + use_alpha, + tone_map); + break; + case OutputKind::RGBFixed16: + assign_linear_rgba( + rgba_pixels, + dst, + fixed16_to_float(read_value(pixel + 0)), + fixed16_to_float(read_value(pixel + 2)), + fixed16_to_float(read_value(pixel + 4)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::RGBFixed16X: + assign_linear_rgba( + rgba_pixels, + dst, + fixed16_to_float(read_value(pixel + 0)), + fixed16_to_float(read_value(pixel + 2)), + fixed16_to_float(read_value(pixel + 4)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::GRAYFixed16: { + const float gray = + fixed16_to_float(read_value(pixel)); + assign_linear_rgba( + rgba_pixels, dst, gray, gray, gray, 1.0f, use_alpha, tone_map); + break; + } + case OutputKind::RGBAFixed32: + assign_linear_rgba( + rgba_pixels, + dst, + fixed32_to_float(read_value(pixel + 0)), + fixed32_to_float(read_value(pixel + 4)), + fixed32_to_float(read_value(pixel + 8)), + fixed32_to_float(read_value(pixel + 12)), + use_alpha, + tone_map); + break; + case OutputKind::RGBFixed32: + assign_linear_rgba( + rgba_pixels, + dst, + fixed32_to_float(read_value(pixel + 0)), + fixed32_to_float(read_value(pixel + 4)), + fixed32_to_float(read_value(pixel + 8)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::RGBFixed32X: + assign_linear_rgba( + rgba_pixels, + dst, + fixed32_to_float(read_value(pixel + 0)), + fixed32_to_float(read_value(pixel + 4)), + fixed32_to_float(read_value(pixel + 8)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::GRAYFixed32: { + const float gray = + fixed32_to_float(read_value(pixel)); + assign_linear_rgba( + rgba_pixels, dst, gray, gray, gray, 1.0f, use_alpha, tone_map); + break; + } + case OutputKind::RGB101010: { + const uint32_t value = read_value(pixel); + assign_rgba( + rgba_pixels, dst, + static_cast(((value >> 20) & 0x3ff) >> 2), + static_cast(((value >> 10) & 0x3ff) >> 2), + static_cast((value & 0x3ff) >> 2), + 255); + break; + } + case OutputKind::RGBE: { + const uint8_t exponent = pixel[3]; + if (exponent == 0) { + assign_rgba(rgba_pixels, dst, 0, 0, 0, 255); + break; + } + + const int adjusted_exponent = static_cast(exponent) - 128 - 8; + const float scale = std::ldexp(1.0f, adjusted_exponent); + assign_rgba( + rgba_pixels, dst, + convert_float_to_u8(static_cast(pixel[0]) * scale), + convert_float_to_u8(static_cast(pixel[1]) * scale), + convert_float_to_u8(static_cast(pixel[2]) * scale), + 255); + break; + } + } + } +} + +template +bool decode_pixels_to_rgba( + int width, + int height, + const DecodeTarget& target, + CopyFn copy_pixels, + bool has_alpha, + std::vector& rgba_pixels) { + const size_t pixel_count = + static_cast(width) * static_cast(height); + const size_t row_bytes = + static_cast(width) * static_cast(target.bytes_per_pixel); + std::vector decoded_pixels(pixel_count * target.bytes_per_pixel); + PKRect rect = {0, 0, width, height}; + + if (!copy_pixels(&rect, decoded_pixels.data(), row_bytes)) { + return false; + } + + rgba_pixels.resize(pixel_count * 4); + convert_decoded_pixels_to_rgba( + decoded_pixels.data(), pixel_count, target, has_alpha, rgba_pixels.data()); + return true; +} +} // namespace + +val decode(std::string jxrimage) { + struct WMPStream* stream = nullptr; + if (CreateWS_Memory(&stream, (void*)jxrimage.data(), jxrimage.size())) { + return val::null(); + } + + PKImageDecode* decoder = nullptr; + if (PKImageDecode_Create_WMP(&decoder) || !decoder) { + if (stream) { + stream->Close(&stream); + } + return val::null(); + } + + if (decoder->Initialize(decoder, stream)) { + decoder->Release(&decoder); + return val::null(); + } + + int width = 0; + int height = 0; + if (decoder->GetSize(decoder, &width, &height) || width <= 0 || height <= 0) { + decoder->Release(&decoder); + return val::null(); + } + + const bool has_alpha = + decoder->WMP.bHasAlpha || decoder->WMP.wmiSCP.uAlphaMode > 0; + + PKPixelFormatGUID source_guid; + std::vector rgba_pixels; + + if (!decoder->GetPixelFormat(decoder, &source_guid)) { + const DecodeTarget* source_target = find_decode_target(source_guid); + if (source_target && + decode_pixels_to_rgba( + width, + height, + *source_target, + [&](const PKRect* rect, uint8_t* pixels, size_t row_bytes) { + return !decoder->Copy( + decoder, + rect, + pixels, + static_cast(row_bytes)); + }, + has_alpha, + rgba_pixels)) { + decoder->Release(&decoder); + return create_image_data(rgba_pixels, width, height); + } + } + + for (const DecodeTarget& candidate : kTargets) { + PKFormatConverter* converter = nullptr; + if (PKCodecFactory_CreateFormatConverter(&converter) || !converter) { + decoder->Release(&decoder); + return val::null(); + } + + if (converter->Initialize(converter, decoder, nullptr, candidate.guid)) { + converter->Release(&converter); + continue; + } + + const bool decoded = decode_pixels_to_rgba( + width, + height, + candidate, + [&](const PKRect* rect, uint8_t* pixels, size_t row_bytes) { + return !converter->Copy( + converter, + rect, + pixels, + static_cast(row_bytes)); + }, + has_alpha, + rgba_pixels); + converter->Release(&converter); + + if (decoded) { + decoder->Release(&decoder); + return create_image_data(rgba_pixels, width, height); + } + } + + decoder->Release(&decoder); + return val::null(); +} + +EMSCRIPTEN_BINDINGS(my_module) { + function("decode", &decode); +} diff --git a/packages/jxr/codec/dec/jxr_dec.d.ts b/packages/jxr/codec/dec/jxr_dec.d.ts new file mode 100644 index 0000000..c6262ab --- /dev/null +++ b/packages/jxr/codec/dec/jxr_dec.d.ts @@ -0,0 +1,7 @@ +export interface JXRModule extends EmscriptenWasm.Module { + decode(data: BufferSource): ImageData | null; +} + +declare var moduleFactory: EmscriptenWasm.ModuleFactory; + +export default moduleFactory; diff --git a/packages/jxr/codec/dec/jxr_dec.js b/packages/jxr/codec/dec/jxr_dec.js new file mode 100644 index 0000000..be6abe5 --- /dev/null +++ b/packages/jxr/codec/dec/jxr_dec.js @@ -0,0 +1,2940 @@ + +var Module = (() => { + var _scriptDir = import.meta.url; + + return ( +function(moduleArg = {}) { + +// include: shell.js +// The Module object: Our interface to the outside world. We import +// and export values on it. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to check if Module already exists (e.g. case 3 above). +// Substitution will be replaced with actual code on later stage of the build, +// this way Closure Compiler will not mangle it (e.g. case 4. above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module = moduleArg; + +// Set up the promise that indicates the Module is initialized +var readyPromiseResolve, readyPromiseReject; +var readyPromise = new Promise((resolve, reject) => { + readyPromiseResolve = resolve; + readyPromiseReject = reject; +}); +["_memory","___indirect_function_table","onRuntimeInitialized"].forEach((prop) => { + if (!Object.getOwnPropertyDescriptor(readyPromise, prop)) { + Object.defineProperty(readyPromise, prop, { + get: () => abort('You are getting ' + prop + ' on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js'), + set: () => abort('You are setting ' + prop + ' on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js'), + }); + } +}); + +// --pre-jses are emitted after the Module integration code, so that they can +// refer to Module (if they choose; they can also define Module) +// include: /src/pre.js +const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; +const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; +const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; + +if (isRunningInCloudFlareWorkers || isRunningInNode) { + if (!globalThis.ImageData) { + // Simple Polyfill for ImageData Object + globalThis.ImageData = class ImageData { + constructor(data, width, height) { + this.data = data; + this.width = width; + this.height = height; + } + }; + } + + if (import.meta.url === undefined) { + import.meta.url = 'https://localhost'; + } + + if (typeof self !== 'undefined' && self.location === undefined) { + self.location = { href: '' }; + } +} +// end include: /src/pre.js + + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = Object.assign({}, Module); + +var arguments_ = []; +var thisProgram = './this.program'; +var quit_ = (status, toThrow) => { + throw toThrow; +}; + +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). + +// Attempt to auto-detect the environment +var ENVIRONMENT_IS_WEB = typeof window == 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function'; +// N.b. Electron.js environment is simultaneously a NODE-environment, but +// also a web environment. +var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (Module['ENVIRONMENT']) { + throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); +} + +// `/` should be present at the end if `scriptDirectory` is not empty +var scriptDirectory = ''; +function locateFile(path) { + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; +} + +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary; + +if (ENVIRONMENT_IS_SHELL) { + + if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + +} else + +// Note that this includes Node.js workers when relevant (pthreads is enabled). +// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and +// ENVIRONMENT_IS_NODE. +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled + scriptDirectory = self.location.href; + } else if (typeof document != 'undefined' && document.currentScript) { // web + scriptDirectory = document.currentScript.src; + } + // When MODULARIZE, this JS may be executed later, after document.currentScript + // is gone, so we saved it, and we use it here instead of any other info. + if (_scriptDir) { + scriptDirectory = _scriptDir; + } + // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. + // otherwise, slice off the final part of the url to find the script directory. + // if scriptDirectory does not contain a slash, lastIndexOf will return -1, + // and scriptDirectory will correctly be replaced with an empty string. + // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #), + // they are removed because they could contain a slash. + if (scriptDirectory.startsWith('blob:')) { + scriptDirectory = ''; + } else { + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, '').lastIndexOf('/')+1); + } + + if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + // Differentiate the Web Worker from the Node Worker case, as reading must + // be done differently. + { +// include: web_or_worker_shell_read.js +read_ = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + } + + if (ENVIRONMENT_IS_WORKER) { + readBinary = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.responseType = 'arraybuffer'; + xhr.send(null); + return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); + }; + } + + readAsync = (url, onload, onerror) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = () => { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + return; + } + onerror(); + }; + xhr.onerror = onerror; + xhr.send(null); + } + +// end include: web_or_worker_shell_read.js + } +} else +{ + throw new Error('environment detection error'); +} + +var out = Module['print'] || console.log.bind(console); +var err = Module['printErr'] || console.error.bind(console); + +// Merge back in the overrides +Object.assign(Module, moduleOverrides); +// Free the object hierarchy contained in the overrides, this lets the GC +// reclaim data used. +moduleOverrides = null; +checkIncomingModuleAPI(); + +// Emit code to handle expected values on the Module object. This applies Module.x +// to the proper local x. This has two benefits: first, we only emit it if it is +// expected to arrive, and second, by using a local everywhere else that can be +// minified. + +if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_'); + +if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram'); + +if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_'); + +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message +// Assertions on removed incoming Module JS APIs. +assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)'); +assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)'); +assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); +assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)'); +assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); +legacyModuleProp('asm', 'wasmExports'); +legacyModuleProp('read', 'read_'); +legacyModuleProp('readAsync', 'readAsync'); +legacyModuleProp('readBinary', 'readBinary'); +legacyModuleProp('setWindowTitle', 'setWindowTitle'); +var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js'; +var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js'; +var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js'; +var FETCHFS = 'FETCHFS is no longer included by default; build with -lfetchfs.js'; +var ICASEFS = 'ICASEFS is no longer included by default; build with -licasefs.js'; +var JSFILEFS = 'JSFILEFS is no longer included by default; build with -ljsfilefs.js'; +var OPFS = 'OPFS is no longer included by default; build with -lopfs.js'; + +var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; + +assert(!ENVIRONMENT_IS_NODE, 'node environment detected but not enabled at build time. Add `node` to `-sENVIRONMENT` to enable.'); + +assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.'); + +// end include: shell.js + +// include: preamble.js +// === Preamble library stuff === + +// Documentation for the public APIs defined in this file must be updated in: +// site/source/docs/api_reference/preamble.js.rst +// A prebuilt local version of the documentation is available at: +// site/build/text/docs/api_reference/preamble.js.txt +// You can also build docs locally as HTML or other formats in site/ +// An online HTML version (which may be of a different version of Emscripten) +// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html + +var wasmBinary; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); + +if (typeof WebAssembly != 'object') { + err('no native wasm support detected'); +} + +// Wasm globals + +var wasmMemory; + +//======================================== +// Runtime essentials +//======================================== + +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. +var EXITSTATUS; + +// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we +// don't define it at all in release modes. This matches the behaviour of +// MINIMAL_RUNTIME. +// TODO(sbc): Make this the default even without STRICT enabled. +/** @type {function(*, string=)} */ +function assert(condition, text) { + if (!condition) { + abort('Assertion failed' + (text ? ': ' + text : '')); + } +} + +// We used to include malloc/free by default in the past. Show a helpful error in +// builds with assertions. + +// Memory management + +var HEAP, +/** @type {!Int8Array} */ + HEAP8, +/** @type {!Uint8Array} */ + HEAPU8, +/** @type {!Int16Array} */ + HEAP16, +/** @type {!Uint16Array} */ + HEAPU16, +/** @type {!Int32Array} */ + HEAP32, +/** @type {!Uint32Array} */ + HEAPU32, +/** @type {!Float32Array} */ + HEAPF32, +/** @type {!Float64Array} */ + HEAPF64; + +// include: runtime_shared.js +function updateMemoryViews() { + var b = wasmMemory.buffer; + Module['HEAP8'] = HEAP8 = new Int8Array(b); + Module['HEAP16'] = HEAP16 = new Int16Array(b); + Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); + Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); + Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); + Module['HEAPF32'] = HEAPF32 = new Float32Array(b); + Module['HEAPF64'] = HEAPF64 = new Float64Array(b); +} +// end include: runtime_shared.js +assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') + +assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined, + 'JS engine does not provide full typed array support'); + +// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY +assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally'); +assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically'); + +// include: runtime_stack_check.js +// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. +function writeStackCookie() { + var max = _emscripten_stack_get_end(); + assert((max & 3) == 0); + // If the stack ends at address zero we write our cookies 4 bytes into the + // stack. This prevents interference with SAFE_HEAP and ASAN which also + // monitor writes to address zero. + if (max == 0) { + max += 4; + } + // The stack grow downwards towards _emscripten_stack_get_end. + // We write cookies to the final two words in the stack and detect if they are + // ever overwritten. + HEAPU32[((max)>>2)] = 0x02135467; + HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE; + // Also test the global address 0 for integrity. + HEAPU32[((0)>>2)] = 1668509029; +} + +function checkStackCookie() { + if (ABORT) return; + var max = _emscripten_stack_get_end(); + // See writeStackCookie(). + if (max == 0) { + max += 4; + } + var cookie1 = HEAPU32[((max)>>2)]; + var cookie2 = HEAPU32[(((max)+(4))>>2)]; + if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) { + abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`); + } + // Also test the global address 0 for integrity. + if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) { + abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); + } +} +// end include: runtime_stack_check.js +// include: runtime_assertions.js +// Endianness check +(function() { + var h16 = new Int16Array(1); + var h8 = new Int8Array(h16.buffer); + h16[0] = 0x6373; + if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'; +})(); + +// end include: runtime_assertions.js +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the main() is called + +var runtimeInitialized = false; + +function preRun() { + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function initRuntime() { + assert(!runtimeInitialized); + runtimeInitialized = true; + + checkStackCookie(); + + + callRuntimeCallbacks(__ATINIT__); +} + +function postRun() { + checkStackCookie(); + + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} + +function addOnExit(cb) { +} + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} + +// include: runtime_math.js +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc + +assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +// end include: runtime_math.js +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// Module.preRun (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled +var runDependencyTracking = {}; + +function getUniqueRunDependency(id) { + var orig = id; + while (1) { + if (!runDependencyTracking[id]) return id; + id = orig + Math.random(); + } +} + +function addRunDependency(id) { + runDependencies++; + + Module['monitorRunDependencies']?.(runDependencies); + + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + if (runDependencyWatcher === null && typeof setInterval != 'undefined') { + // Check for missing dependencies every few seconds + runDependencyWatcher = setInterval(() => { + if (ABORT) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + return; + } + var shown = false; + for (var dep in runDependencyTracking) { + if (!shown) { + shown = true; + err('still waiting on run dependencies:'); + } + err(`dependency: ${dep}`); + } + if (shown) { + err('(end of list)'); + } + }, 10000); + } + } else { + err('warning: run dependency added without ID'); + } +} + +function removeRunDependency(id) { + runDependencies--; + + Module['monitorRunDependencies']?.(runDependencies); + + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } else { + err('warning: run dependency removed without ID'); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} + +/** @param {string|number=} what */ +function abort(what) { + Module['onAbort']?.(what); + + what = 'Aborted(' + what + ')'; + // TODO(sbc): Should we remove printing and leave it up to whoever + // catches the exception? + err(what); + + ABORT = true; + EXITSTATUS = 1; + + // Use a wasm runtime error, because a JS error might be seen as a foreign + // exception, which means we'd run destructors on it. We need the error to + // simply make the program stop. + // FIXME This approach does not work in Wasm EH because it currently does not assume + // all RuntimeErrors are from traps; it decides whether a RuntimeError is from + // a trap or not based on a hidden field within the object. So at the moment + // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that + // allows this in the wasm spec. + + // Suppress closure compiler warning here. Closure compiler's builtin extern + // definition for WebAssembly.RuntimeError claims it takes no arguments even + // though it can. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. + /** @suppress {checkTypes} */ + var e = new WebAssembly.RuntimeError(what); + + readyPromiseReject(e); + // Throw the error whether or not MODULARIZE is set because abort is used + // in code paths apart from instantiation where an exception is expected + // to be thrown when abort is called. + throw e; +} + +// include: memoryprofiler.js +// end include: memoryprofiler.js +// show errors on likely calls to FS when it was not included +var FS = { + error() { + abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -sFORCE_FILESYSTEM'); + }, + init() { FS.error() }, + createDataFile() { FS.error() }, + createPreloadedFile() { FS.error() }, + createLazyFile() { FS.error() }, + open() { FS.error() }, + mkdev() { FS.error() }, + registerDevice() { FS.error() }, + analyzePath() { FS.error() }, + + ErrnoError() { FS.error() }, +}; +Module['FS_createDataFile'] = FS.createDataFile; +Module['FS_createPreloadedFile'] = FS.createPreloadedFile; + +// include: URIUtils.js +// Prefix of data URIs emitted by SINGLE_FILE and related options. +var dataURIPrefix = 'data:application/octet-stream;base64,'; + +/** + * Indicates whether filename is a base64 data URI. + * @noinline + */ +var isDataURI = (filename) => filename.startsWith(dataURIPrefix); + +/** + * Indicates whether filename is delivered via file protocol (as opposed to http/https) + * @noinline + */ +var isFileURI = (filename) => filename.startsWith('file://'); +// end include: URIUtils.js +function createExportWrapper(name, nargs) { + return (...args) => { + assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`); + var f = wasmExports[name]; + assert(f, `exported native function \`${name}\` not found`); + // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled. + assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`); + return f(...args); + }; +} + +// include: runtime_exceptions.js +// end include: runtime_exceptions.js +var wasmBinaryFile; +if (Module['locateFile']) { + wasmBinaryFile = 'jxr_dec.wasm'; + if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); + } +} else { + // Use bundler-friendly `new URL(..., import.meta.url)` pattern; works in browsers too. + wasmBinaryFile = new URL('jxr_dec.wasm', import.meta.url).href; +} + +function getBinarySync(file) { + if (file == wasmBinaryFile && wasmBinary) { + return new Uint8Array(wasmBinary); + } + if (readBinary) { + return readBinary(file); + } + throw 'both async and sync fetching of the wasm failed'; +} + +function getBinaryPromise(binaryFile) { + // If we don't have the binary yet, try to load it asynchronously. + // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. + // See https://github.com/github/fetch/pull/92#issuecomment-140665932 + // Cordova or Electron apps are typically loaded from a file:// url. + // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. + if (!wasmBinary + && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { + if (typeof fetch == 'function' + ) { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + throw `failed to load wasm binary file at '${binaryFile}'`; + } + return response['arrayBuffer'](); + }).catch(() => getBinarySync(binaryFile)); + } + } + + // Otherwise, getBinarySync should be able to get it synchronously + return Promise.resolve().then(() => getBinarySync(binaryFile)); +} + +function instantiateArrayBuffer(binaryFile, imports, receiver) { + return getBinaryPromise(binaryFile).then((binary) => { + return WebAssembly.instantiate(binary, imports); + }).then(receiver, (reason) => { + err(`failed to asynchronously prepare wasm: ${reason}`); + + // Warn on some common problems. + if (isFileURI(wasmBinaryFile)) { + err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`); + } + abort(reason); + }); +} + +function instantiateAsync(binary, binaryFile, imports, callback) { + if (!binary && + typeof WebAssembly.instantiateStreaming == 'function' && + !isDataURI(binaryFile) && + typeof fetch == 'function') { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + // Suppress closure warning here since the upstream definition for + // instantiateStreaming only allows Promise rather than + // an actual Response. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. + /** @suppress {checkTypes} */ + var result = WebAssembly.instantiateStreaming(response, imports); + + return result.then( + callback, + function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err(`wasm streaming compile failed: ${reason}`); + err('falling back to ArrayBuffer instantiation'); + return instantiateArrayBuffer(binaryFile, imports, callback); + }); + }); + } + return instantiateArrayBuffer(binaryFile, imports, callback); +} + +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +function createWasm() { + // prepare imports + var info = { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + }; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + /** @param {WebAssembly.Module=} module*/ + function receiveInstance(instance, module) { + wasmExports = instance.exports; + + + + wasmMemory = wasmExports['memory']; + + assert(wasmMemory, 'memory not found in wasm exports'); + updateMemoryViews(); + + wasmTable = wasmExports['__indirect_function_table']; + + assert(wasmTable, 'table not found in wasm exports'); + + addOnInit(wasmExports['__wasm_call_ctors']); + + removeRunDependency('wasm-instantiate'); + return wasmExports; + } + // wait for the pthread pool (if any) + addRunDependency('wasm-instantiate'); + + // Prefer streaming instantiation if available. + // Async compilation can be confusing when an error on the page overwrites Module + // (for example, if the order of elements is wrong, and the one defining Module is + // later), so we save Module and check it later. + var trueModule = Module; + function receiveInstantiationResult(result) { + // 'result' is a ResultObject object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); + trueModule = null; + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. + // When the regression is fixed, can restore the above PTHREADS-enabled path. + receiveInstance(result['instance']); + } + + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to + // run the instantiation parallel to any other async startup actions they are + // performing. + // Also pthreads and wasm workers initialize the wasm instance through this + // path. + if (Module['instantiateWasm']) { + + try { + return Module['instantiateWasm'](info, receiveInstance); + } catch(e) { + err(`Module.instantiateWasm callback failed with error: ${e}`); + // If instantiation fails, reject the module ready promise. + readyPromiseReject(e); + } + } + + // If instantiation fails, reject the module ready promise. + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject); + return {}; // no exports yet; we'll fill them in later +} + +// Globals used by JS i64 conversions (see makeSetValue) +var tempDouble; +var tempI64; + +// include: runtime_debug.js +function legacyModuleProp(prop, newName, incoming=true) { + if (!Object.getOwnPropertyDescriptor(Module, prop)) { + Object.defineProperty(Module, prop, { + configurable: true, + get() { + let extra = incoming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : ''; + abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra); + + } + }); + } +} + +function ignoredModuleProp(prop) { + if (Object.getOwnPropertyDescriptor(Module, prop)) { + abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`); + } +} + +// forcing the filesystem exports a few things by default +function isExportedByForceFilesystem(name) { + return name === 'FS_createPath' || + name === 'FS_createDataFile' || + name === 'FS_createPreloadedFile' || + name === 'FS_unlink' || + name === 'addRunDependency' || + // The old FS has some functionality that WasmFS lacks. + name === 'FS_createLazyFile' || + name === 'FS_createDevice' || + name === 'removeRunDependency'; +} + +function missingGlobal(sym, msg) { + if (typeof globalThis != 'undefined') { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`); + return undefined; + } + }); + } +} + +missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer'); +missingGlobal('asm', 'Please use wasmExports instead'); + +function missingLibrarySymbol(sym) { + if (typeof globalThis != 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + // Can't `abort()` here because it would break code that does runtime + // checks. e.g. `if (typeof SDL === 'undefined')`. + var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`; + // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in + // library.js, which means $name for a JS name with no prefix, or name + // for a JS name like _name. + var librarySymbol = sym; + if (!librarySymbol.startsWith('_')) { + librarySymbol = '$' + sym; + } + msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + warnOnce(msg); + return undefined; + } + }); + } + // Any symbol that is not included from the JS library is also (by definition) + // not exported on the Module object. + unexportedRuntimeSymbol(sym); +} + +function unexportedRuntimeSymbol(sym) { + if (!Object.getOwnPropertyDescriptor(Module, sym)) { + Object.defineProperty(Module, sym, { + configurable: true, + get() { + var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + abort(msg); + } + }); + } +} + +// Used by XXXXX_DEBUG settings to output debug messages. +function dbg(...args) { + // TODO(sbc): Make this configurable somehow. Its not always convenient for + // logging to show up as warnings. + console.warn(...args); +} +// end include: runtime_debug.js +// === Body === +// end include: preamble.js + + + /** @constructor */ + function ExitStatus(status) { + this.name = 'ExitStatus'; + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + // Pass the module as the first argument. + callbacks.shift()(Module); + } + }; + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[ptr]; + case 'i8': return HEAP8[ptr]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': abort('to do getValue(i64) use WASM_BIGINT'); + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + + var noExitRuntime = Module['noExitRuntime'] || true; + + var ptrToString = (ptr) => { + assert(typeof ptr === 'number'); + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + ptr >>>= 0; + return '0x' + ptr.toString(16).padStart(8, '0'); + }; + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[ptr] = value; break; + case 'i8': HEAP8[ptr] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': abort('to do setValue(i64) use WASM_BIGINT'); + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + + var stackRestore = (val) => __emscripten_stack_restore(val); + + var stackSave = () => _emscripten_stack_get_current(); + + var warnOnce = (text) => { + warnOnce.shown ||= {}; + if (!warnOnce.shown[text]) { + warnOnce.shown[text] = 1; + err(text); + } + }; + + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var endIdx = idx + maxBytesToRead; + + var str = ''; + while (!(idx >= endIdx)) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = heapOrArray[idx++]; + // If not building with TextDecoder enabled, we don't know the string + // length, so scan for \0 byte. + // If building with TextDecoder, we know exactly at what byte index the + // string ends, so checking for nulls here would be redundant. + if (!u0) return str; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + return str; + }; + + /** + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index (i.e. maxBytesToRead will not + * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing + * frequent uses of UTF8ToString() with and without maxBytesToRead may throw + * JS JIT optimizations off, so it is worth to consider consistently using one + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead) => { + assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`); + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; + }; + var ___assert_fail = (condition, filename, line, func) => { + abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); + }; + + class ExceptionInfo { + // excPtr - Thrown object pointer to wrap. Metadata pointer is calculated from it. + constructor(excPtr) { + this.excPtr = excPtr; + this.ptr = excPtr - 24; + } + + set_type(type) { + HEAPU32[(((this.ptr)+(4))>>2)] = type; + } + + get_type() { + return HEAPU32[(((this.ptr)+(4))>>2)]; + } + + set_destructor(destructor) { + HEAPU32[(((this.ptr)+(8))>>2)] = destructor; + } + + get_destructor() { + return HEAPU32[(((this.ptr)+(8))>>2)]; + } + + set_caught(caught) { + caught = caught ? 1 : 0; + HEAP8[(this.ptr)+(12)] = caught; + } + + get_caught() { + return HEAP8[(this.ptr)+(12)] != 0; + } + + set_rethrown(rethrown) { + rethrown = rethrown ? 1 : 0; + HEAP8[(this.ptr)+(13)] = rethrown; + } + + get_rethrown() { + return HEAP8[(this.ptr)+(13)] != 0; + } + + // Initialize native structure fields. Should be called once after allocated. + init(type, destructor) { + this.set_adjusted_ptr(0); + this.set_type(type); + this.set_destructor(destructor); + } + + set_adjusted_ptr(adjustedPtr) { + HEAPU32[(((this.ptr)+(16))>>2)] = adjustedPtr; + } + + get_adjusted_ptr() { + return HEAPU32[(((this.ptr)+(16))>>2)]; + } + + // Get pointer which is expected to be received by catch clause in C++ code. It may be adjusted + // when the pointer is casted to some of the exception object base classes (e.g. when virtual + // inheritance is used). When a pointer is thrown this method should return the thrown pointer + // itself. + get_exception_ptr() { + // Work around a fastcomp bug, this code is still included for some reason in a build without + // exceptions support. + var isPointer = ___cxa_is_pointer_type(this.get_type()); + if (isPointer) { + return HEAPU32[((this.excPtr)>>2)]; + } + var adjusted = this.get_adjusted_ptr(); + if (adjusted !== 0) return adjusted; + return this.excPtr; + } + } + + var exceptionLast = 0; + + var uncaughtExceptionCount = 0; + var ___cxa_throw = (ptr, type, destructor) => { + var info = new ExceptionInfo(ptr); + // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception. + info.init(type, destructor); + exceptionLast = ptr; + uncaughtExceptionCount++; + assert(false, 'Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.'); + }; + + var __embind_register_bigint = (primitiveType, name, size, minRange, maxRange) => {}; + + var embind_init_charCodes = () => { + var codes = new Array(256); + for (var i = 0; i < 256; ++i) { + codes[i] = String.fromCharCode(i); + } + embind_charCodes = codes; + }; + var embind_charCodes; + var readLatin1String = (ptr) => { + var ret = ""; + var c = ptr; + while (HEAPU8[c]) { + ret += embind_charCodes[HEAPU8[c++]]; + } + return ret; + }; + + var awaitingDependencies = { + }; + + var registeredTypes = { + }; + + var typeDependencies = { + }; + + var BindingError; + var throwBindingError = (message) => { throw new BindingError(message); }; + + + + + var InternalError; + var throwInternalError = (message) => { throw new InternalError(message); }; + var whenDependentTypesAreResolved = (myTypes, dependentTypes, getTypeConverters) => { + myTypes.forEach(function(type) { + typeDependencies[type] = dependentTypes; + }); + + function onComplete(typeConverters) { + var myTypeConverters = getTypeConverters(typeConverters); + if (myTypeConverters.length !== myTypes.length) { + throwInternalError('Mismatched type converter count'); + } + for (var i = 0; i < myTypes.length; ++i) { + registerType(myTypes[i], myTypeConverters[i]); + } + } + + var typeConverters = new Array(dependentTypes.length); + var unregisteredTypes = []; + var registered = 0; + dependentTypes.forEach((dt, i) => { + if (registeredTypes.hasOwnProperty(dt)) { + typeConverters[i] = registeredTypes[dt]; + } else { + unregisteredTypes.push(dt); + if (!awaitingDependencies.hasOwnProperty(dt)) { + awaitingDependencies[dt] = []; + } + awaitingDependencies[dt].push(() => { + typeConverters[i] = registeredTypes[dt]; + ++registered; + if (registered === unregisteredTypes.length) { + onComplete(typeConverters); + } + }); + } + }); + if (0 === unregisteredTypes.length) { + onComplete(typeConverters); + } + }; + /** @param {Object=} options */ + function sharedRegisterType(rawType, registeredInstance, options = {}) { + var name = registeredInstance.name; + if (!rawType) { + throwBindingError(`type "${name}" must have a positive integer typeid pointer`); + } + if (registeredTypes.hasOwnProperty(rawType)) { + if (options.ignoreDuplicateRegistrations) { + return; + } else { + throwBindingError(`Cannot register type '${name}' twice`); + } + } + + registeredTypes[rawType] = registeredInstance; + delete typeDependencies[rawType]; + + if (awaitingDependencies.hasOwnProperty(rawType)) { + var callbacks = awaitingDependencies[rawType]; + delete awaitingDependencies[rawType]; + callbacks.forEach((cb) => cb()); + } + } + /** @param {Object=} options */ + function registerType(rawType, registeredInstance, options = {}) { + if (!('argPackAdvance' in registeredInstance)) { + throw new TypeError('registerType registeredInstance requires argPackAdvance'); + } + return sharedRegisterType(rawType, registeredInstance, options); + } + + var GenericWireTypeSize = 8; + /** @suppress {globalThis} */ + var __embind_register_bool = (rawType, name, trueValue, falseValue) => { + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': function(wt) { + // ambiguous emscripten ABI: sometimes return values are + // true or false, and sometimes integers (0 or 1) + return !!wt; + }, + 'toWireType': function(destructors, o) { + return o ? trueValue : falseValue; + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': function(pointer) { + return this['fromWireType'](HEAPU8[pointer]); + }, + destructorFunction: null, // This type does not need a destructor + }); + }; + + + var emval_freelist = []; + + var emval_handles = []; + var __emval_decref = (handle) => { + if (handle > 9 && 0 === --emval_handles[handle + 1]) { + assert(emval_handles[handle] !== undefined, `Decref for unallocated handle.`); + emval_handles[handle] = undefined; + emval_freelist.push(handle); + } + }; + + + + + + var count_emval_handles = () => { + return emval_handles.length / 2 - 5 - emval_freelist.length; + }; + + var init_emval = () => { + // reserve 0 and some special values. These never get de-allocated. + emval_handles.push( + 0, 1, + undefined, 1, + null, 1, + true, 1, + false, 1, + ); + assert(emval_handles.length === 5 * 2); + Module['count_emval_handles'] = count_emval_handles; + }; + var Emval = { + toValue:(handle) => { + if (!handle) { + throwBindingError('Cannot use deleted val. handle = ' + handle); + } + // handle 2 is supposed to be `undefined`. + assert(handle === 2 || emval_handles[handle] !== undefined && handle % 2 === 0, `invalid handle: ${handle}`); + return emval_handles[handle]; + }, + toHandle:(value) => { + switch (value) { + case undefined: return 2; + case null: return 4; + case true: return 6; + case false: return 8; + default:{ + const handle = emval_freelist.pop() || emval_handles.length; + emval_handles[handle] = value; + emval_handles[handle + 1] = 1; + return handle; + } + } + }, + }; + + /** @suppress {globalThis} */ + function readPointer(pointer) { + return this['fromWireType'](HEAPU32[((pointer)>>2)]); + } + + var EmValType = { + name: 'emscripten::val', + 'fromWireType': (handle) => { + var rv = Emval.toValue(handle); + __emval_decref(handle); + return rv; + }, + 'toWireType': (destructors, value) => Emval.toHandle(value), + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, + destructorFunction: null, // This type does not need a destructor + + // TODO: do we need a deleteObject here? write a test where + // emval is passed into JS via an interface + }; + var __embind_register_emval = (rawType) => registerType(rawType, EmValType); + + var embindRepr = (v) => { + if (v === null) { + return 'null'; + } + var t = typeof v; + if (t === 'object' || t === 'array' || t === 'function') { + return v.toString(); + } else { + return '' + v; + } + }; + + var floatReadValueFromPointer = (name, width) => { + switch (width) { + case 4: return function(pointer) { + return this['fromWireType'](HEAPF32[((pointer)>>2)]); + }; + case 8: return function(pointer) { + return this['fromWireType'](HEAPF64[((pointer)>>3)]); + }; + default: + throw new TypeError(`invalid float width (${width}): ${name}`); + } + }; + + + var __embind_register_float = (rawType, name, size) => { + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': (value) => value, + 'toWireType': (destructors, value) => { + if (typeof value != "number" && typeof value != "boolean") { + throw new TypeError(`Cannot convert ${embindRepr(value)} to ${this.name}`); + } + // The VM will perform JS to Wasm value conversion, according to the spec: + // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue + return value; + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': floatReadValueFromPointer(name, size), + destructorFunction: null, // This type does not need a destructor + }); + }; + + var createNamedFunction = (name, body) => Object.defineProperty(body, 'name', { + value: name + }); + + var runDestructors = (destructors) => { + while (destructors.length) { + var ptr = destructors.pop(); + var del = destructors.pop(); + del(ptr); + } + }; + + + function usesDestructorStack(argTypes) { + // Skip return value at index 0 - it's not deleted here. + for (var i = 1; i < argTypes.length; ++i) { + // The type does not define a destructor function - must use dynamic stack + if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) { + return true; + } + } + return false; + } + function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc, /** boolean= */ isAsync) { + // humanName: a human-readable string name for the function to be generated. + // argTypes: An array that contains the embind type objects for all types in the function signature. + // argTypes[0] is the type object for the function return value. + // argTypes[1] is the type object for function this object/class type, or null if not crafting an invoker for a class method. + // argTypes[2...] are the actual function parameters. + // classType: The embind type object for the class to be bound, or null if this is not a method of a class. + // cppInvokerFunc: JS Function object to the C++-side function that interops into C++ code. + // cppTargetFunc: Function pointer (an integer to FUNCTION_TABLE) to the target C++ function the cppInvokerFunc will end up calling. + // isAsync: Optional. If true, returns an async function. Async bindings are only supported with JSPI. + var argCount = argTypes.length; + + if (argCount < 2) { + throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!"); + } + + assert(!isAsync, 'Async bindings are only supported with JSPI.'); + + var isClassMethodFunc = (argTypes[1] !== null && classType !== null); + + // Free functions with signature "void function()" do not need an invoker that marshalls between wire types. + // TODO: This omits argument count check - enable only at -O3 or similar. + // if (ENABLE_UNSAFE_OPTS && argCount == 2 && argTypes[0].name == "void" && !isClassMethodFunc) { + // return FUNCTION_TABLE[fn]; + // } + + // Determine if we need to use a dynamic stack to store the destructors for the function parameters. + // TODO: Remove this completely once all function invokers are being dynamically generated. + var needsDestructorStack = usesDestructorStack(argTypes); + + var returns = (argTypes[0].name !== "void"); + + var expectedArgCount = argCount - 2; + var argsWired = new Array(expectedArgCount); + var invokerFuncArgs = []; + var destructors = []; + var invokerFn = function(...args) { + if (args.length !== expectedArgCount) { + throwBindingError(`function ${humanName} called with ${args.length} arguments, expected ${expectedArgCount}`); + } + destructors.length = 0; + var thisWired; + invokerFuncArgs.length = isClassMethodFunc ? 2 : 1; + invokerFuncArgs[0] = cppTargetFunc; + if (isClassMethodFunc) { + thisWired = argTypes[1]['toWireType'](destructors, this); + invokerFuncArgs[1] = thisWired; + } + for (var i = 0; i < expectedArgCount; ++i) { + argsWired[i] = argTypes[i + 2]['toWireType'](destructors, args[i]); + invokerFuncArgs.push(argsWired[i]); + } + + var rv = cppInvokerFunc(...invokerFuncArgs); + + function onDone(rv) { + if (needsDestructorStack) { + runDestructors(destructors); + } else { + for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; i++) { + var param = i === 1 ? thisWired : argsWired[i - 2]; + if (argTypes[i].destructorFunction !== null) { + argTypes[i].destructorFunction(param); + } + } + } + + if (returns) { + return argTypes[0]['fromWireType'](rv); + } + } + + return onDone(rv); + }; + return createNamedFunction(humanName, invokerFn); + } + + var ensureOverloadTable = (proto, methodName, humanName) => { + if (undefined === proto[methodName].overloadTable) { + var prevFunc = proto[methodName]; + // Inject an overload resolver function that routes to the appropriate overload based on the number of arguments. + proto[methodName] = function(...args) { + // TODO This check can be removed in -O3 level "unsafe" optimizations. + if (!proto[methodName].overloadTable.hasOwnProperty(args.length)) { + throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`); + } + return proto[methodName].overloadTable[args.length].apply(this, args); + }; + // Move the previous function into the overload table. + proto[methodName].overloadTable = []; + proto[methodName].overloadTable[prevFunc.argCount] = prevFunc; + } + }; + + /** @param {number=} numArguments */ + var exposePublicSymbol = (name, value, numArguments) => { + if (Module.hasOwnProperty(name)) { + if (undefined === numArguments || (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments])) { + throwBindingError(`Cannot register public name '${name}' twice`); + } + + // We are exposing a function with the same name as an existing function. Create an overload table and a function selector + // that routes between the two. + ensureOverloadTable(Module, name, name); + if (Module.hasOwnProperty(numArguments)) { + throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`); + } + // Add the new function into the overload table. + Module[name].overloadTable[numArguments] = value; + } + else { + Module[name] = value; + if (undefined !== numArguments) { + Module[name].numArguments = numArguments; + } + } + }; + + var heap32VectorToArray = (count, firstElement) => { + var array = []; + for (var i = 0; i < count; i++) { + // TODO(https://github.com/emscripten-core/emscripten/issues/17310): + // Find a way to hoist the `>> 2` or `>> 3` out of this loop. + array.push(HEAPU32[(((firstElement)+(i * 4))>>2)]); + } + return array; + }; + + + /** @param {number=} numArguments */ + var replacePublicSymbol = (name, value, numArguments) => { + if (!Module.hasOwnProperty(name)) { + throwInternalError('Replacing nonexistent public symbol'); + } + // If there's an overload table for this symbol, replace the symbol in the overload table instead. + if (undefined !== Module[name].overloadTable && undefined !== numArguments) { + Module[name].overloadTable[numArguments] = value; + } + else { + Module[name] = value; + Module[name].argCount = numArguments; + } + }; + + + + var dynCallLegacy = (sig, ptr, args) => { + sig = sig.replace(/p/g, 'i') + assert(('dynCall_' + sig) in Module, `bad function pointer type - dynCall function not found for sig '${sig}'`); + if (args?.length) { + // j (64-bit integer) must be passed in as two numbers [low 32, high 32]. + assert(args.length === sig.substring(1).replace(/j/g, '--').length); + } else { + assert(sig.length == 1); + } + var f = Module['dynCall_' + sig]; + return f(ptr, ...args); + }; + + var wasmTableMirror = []; + + var wasmTable; + var getWasmTableEntry = (funcPtr) => { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); + } + assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!'); + return func; + }; + + var dynCall = (sig, ptr, args = []) => { + // Without WASM_BIGINT support we cannot directly call function with i64 as + // part of their signature, so we rely on the dynCall functions generated by + // wasm-emscripten-finalize + if (sig.includes('j')) { + return dynCallLegacy(sig, ptr, args); + } + assert(getWasmTableEntry(ptr), `missing table entry in dynCall: ${ptr}`); + var rtn = getWasmTableEntry(ptr)(...args); + return rtn; + }; + var getDynCaller = (sig, ptr) => { + assert(sig.includes('j') || sig.includes('p'), 'getDynCaller should only be called with i64 sigs') + return (...args) => dynCall(sig, ptr, args); + }; + + + var embind__requireFunction = (signature, rawFunction) => { + signature = readLatin1String(signature); + + function makeDynCaller() { + if (signature.includes('j')) { + return getDynCaller(signature, rawFunction); + } + return getWasmTableEntry(rawFunction); + } + + var fp = makeDynCaller(); + if (typeof fp != "function") { + throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`); + } + return fp; + }; + + + + var extendError = (baseErrorType, errorName) => { + var errorClass = createNamedFunction(errorName, function(message) { + this.name = errorName; + this.message = message; + + var stack = (new Error(message)).stack; + if (stack !== undefined) { + this.stack = this.toString() + '\n' + + stack.replace(/^Error(:[^\n]*)?\n/, ''); + } + }); + errorClass.prototype = Object.create(baseErrorType.prototype); + errorClass.prototype.constructor = errorClass; + errorClass.prototype.toString = function() { + if (this.message === undefined) { + return this.name; + } else { + return `${this.name}: ${this.message}`; + } + }; + + return errorClass; + }; + var UnboundTypeError; + + + + var getTypeName = (type) => { + var ptr = ___getTypeName(type); + var rv = readLatin1String(ptr); + _free(ptr); + return rv; + }; + var throwUnboundTypeError = (message, types) => { + var unboundTypes = []; + var seen = {}; + function visit(type) { + if (seen[type]) { + return; + } + if (registeredTypes[type]) { + return; + } + if (typeDependencies[type]) { + typeDependencies[type].forEach(visit); + return; + } + unboundTypes.push(type); + seen[type] = true; + } + types.forEach(visit); + + throw new UnboundTypeError(`${message}: ` + unboundTypes.map(getTypeName).join([', '])); + }; + + + var getFunctionName = (signature) => { + signature = signature.trim(); + const argsIndex = signature.indexOf("("); + if (argsIndex !== -1) { + assert(signature[signature.length - 1] == ")", "Parentheses for argument names should match."); + return signature.substr(0, argsIndex); + } else { + return signature; + } + }; + var __embind_register_function = (name, argCount, rawArgTypesAddr, signature, rawInvoker, fn, isAsync) => { + var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); + name = readLatin1String(name); + name = getFunctionName(name); + + rawInvoker = embind__requireFunction(signature, rawInvoker); + + exposePublicSymbol(name, function() { + throwUnboundTypeError(`Cannot call ${name} due to unbound types`, argTypes); + }, argCount - 1); + + whenDependentTypesAreResolved([], argTypes, (argTypes) => { + var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */); + replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn, isAsync), argCount - 1); + return []; + }); + }; + + + var integerReadValueFromPointer = (name, width, signed) => { + // integers are quite common, so generate very specialized functions + switch (width) { + case 1: return signed ? + (pointer) => HEAP8[pointer] : + (pointer) => HEAPU8[pointer]; + case 2: return signed ? + (pointer) => HEAP16[((pointer)>>1)] : + (pointer) => HEAPU16[((pointer)>>1)] + case 4: return signed ? + (pointer) => HEAP32[((pointer)>>2)] : + (pointer) => HEAPU32[((pointer)>>2)] + default: + throw new TypeError(`invalid integer width (${width}): ${name}`); + } + }; + + + /** @suppress {globalThis} */ + var __embind_register_integer = (primitiveType, name, size, minRange, maxRange) => { + name = readLatin1String(name); + // LLVM doesn't have signed and unsigned 32-bit types, so u32 literals come + // out as 'i32 -1'. Always treat those as max u32. + if (maxRange === -1) { + maxRange = 4294967295; + } + + var fromWireType = (value) => value; + + if (minRange === 0) { + var bitshift = 32 - 8*size; + fromWireType = (value) => (value << bitshift) >>> bitshift; + } + + var isUnsignedType = (name.includes('unsigned')); + var checkAssertions = (value, toTypeName) => { + if (typeof value != "number" && typeof value != "boolean") { + throw new TypeError(`Cannot convert "${embindRepr(value)}" to ${toTypeName}`); + } + if (value < minRange || value > maxRange) { + throw new TypeError(`Passing a number "${embindRepr(value)}" from JS side to C/C++ side to an argument of type "${name}", which is outside the valid range [${minRange}, ${maxRange}]!`); + } + } + var toWireType; + if (isUnsignedType) { + toWireType = function(destructors, value) { + checkAssertions(value, this.name); + return value >>> 0; + } + } else { + toWireType = function(destructors, value) { + checkAssertions(value, this.name); + // The VM will perform JS to Wasm value conversion, according to the spec: + // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue + return value; + } + } + registerType(primitiveType, { + name, + 'fromWireType': fromWireType, + 'toWireType': toWireType, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': integerReadValueFromPointer(name, size, minRange !== 0), + destructorFunction: null, // This type does not need a destructor + }); + }; + + + var __embind_register_memory_view = (rawType, dataTypeIndex, name) => { + var typeMapping = [ + Int8Array, + Uint8Array, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + ]; + + var TA = typeMapping[dataTypeIndex]; + + function decodeMemoryView(handle) { + var size = HEAPU32[((handle)>>2)]; + var data = HEAPU32[(((handle)+(4))>>2)]; + return new TA(HEAP8.buffer, data, size); + } + + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': decodeMemoryView, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': decodeMemoryView, + }, { + ignoreDuplicateRegistrations: true, + }); + }; + + + + + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`); + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.charCodeAt(i); // possibly a lead surrogate + if (u >= 0xD800 && u <= 0xDFFF) { + var u1 = str.charCodeAt(++i); + u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); + } + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; + }; + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + }; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var c = str.charCodeAt(i); // possibly a lead surrogate + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + + + + var __embind_register_std_string = (rawType, name) => { + name = readLatin1String(name); + var stdStringIsUTF8 + //process only std::string bindings with UTF8 support, in contrast to e.g. std::basic_string + = (name === "std::string"); + + registerType(rawType, { + name, + // For some method names we use string keys here since they are part of + // the public/external API and/or used by the runtime-generated code. + 'fromWireType'(value) { + var length = HEAPU32[((value)>>2)]; + var payload = value + 4; + + var str; + if (stdStringIsUTF8) { + var decodeStartPtr = payload; + // Looping here to support possible embedded '0' bytes + for (var i = 0; i <= length; ++i) { + var currentBytePtr = payload + i; + if (i == length || HEAPU8[currentBytePtr] == 0) { + var maxRead = currentBytePtr - decodeStartPtr; + var stringSegment = UTF8ToString(decodeStartPtr, maxRead); + if (str === undefined) { + str = stringSegment; + } else { + str += String.fromCharCode(0); + str += stringSegment; + } + decodeStartPtr = currentBytePtr + 1; + } + } + } else { + var a = new Array(length); + for (var i = 0; i < length; ++i) { + a[i] = String.fromCharCode(HEAPU8[payload + i]); + } + str = a.join(''); + } + + _free(value); + + return str; + }, + 'toWireType'(destructors, value) { + if (value instanceof ArrayBuffer) { + value = new Uint8Array(value); + } + + var length; + var valueIsOfTypeString = (typeof value == 'string'); + + if (!(valueIsOfTypeString || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Int8Array)) { + throwBindingError('Cannot pass non-string to std::string'); + } + if (stdStringIsUTF8 && valueIsOfTypeString) { + length = lengthBytesUTF8(value); + } else { + length = value.length; + } + + // assumes POINTER_SIZE alignment + var base = _malloc(4 + length + 1); + var ptr = base + 4; + HEAPU32[((base)>>2)] = length; + if (stdStringIsUTF8 && valueIsOfTypeString) { + stringToUTF8(value, ptr, length + 1); + } else { + if (valueIsOfTypeString) { + for (var i = 0; i < length; ++i) { + var charCode = value.charCodeAt(i); + if (charCode > 255) { + _free(ptr); + throwBindingError('String has UTF-16 code units that do not fit in 8 bits'); + } + HEAPU8[ptr + i] = charCode; + } + } else { + for (var i = 0; i < length; ++i) { + HEAPU8[ptr + i] = value[i]; + } + } + } + + if (destructors !== null) { + destructors.push(_free, base); + } + return base; + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, + destructorFunction(ptr) { + _free(ptr); + }, + }); + }; + + + + + var UTF16ToString = (ptr, maxBytesToRead) => { + assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!'); + + // Fallback: decode without UTF16Decoder + var str = ''; + + // If maxBytesToRead is not passed explicitly, it will be undefined, and the + // for-loop's condition will always evaluate to true. The loop is then + // terminated on the first null char. + for (var i = 0; !(i >= maxBytesToRead / 2); ++i) { + var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; + if (codeUnit == 0) break; + // fromCharCode constructs a character from a UTF-16 code unit, so we can + // pass the UTF16 string right through. + str += String.fromCharCode(codeUnit); + } + + return str; + }; + + var stringToUTF16 = (str, outPtr, maxBytesToWrite) => { + assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!'); + assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. + maxBytesToWrite ??= 0x7FFFFFFF; + if (maxBytesToWrite < 2) return 0; + maxBytesToWrite -= 2; // Null terminator. + var startPtr = outPtr; + var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; + for (var i = 0; i < numCharsToWrite; ++i) { + // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + HEAP16[((outPtr)>>1)] = codeUnit; + outPtr += 2; + } + // Null-terminate the pointer to the HEAP. + HEAP16[((outPtr)>>1)] = 0; + return outPtr - startPtr; + }; + + var lengthBytesUTF16 = (str) => { + return str.length*2; + }; + + var UTF32ToString = (ptr, maxBytesToRead) => { + assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!'); + var i = 0; + + var str = ''; + // If maxBytesToRead is not passed explicitly, it will be undefined, and this + // will always evaluate to true. This saves on code size. + while (!(i >= maxBytesToRead / 4)) { + var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; + if (utf32 == 0) break; + ++i; + // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + if (utf32 >= 0x10000) { + var ch = utf32 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } else { + str += String.fromCharCode(utf32); + } + } + return str; + }; + + var stringToUTF32 = (str, outPtr, maxBytesToWrite) => { + assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!'); + assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. + maxBytesToWrite ??= 0x7FFFFFFF; + if (maxBytesToWrite < 4) return 0; + var startPtr = outPtr; + var endPtr = startPtr + maxBytesToWrite - 4; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { + var trailSurrogate = str.charCodeAt(++i); + codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); + } + HEAP32[((outPtr)>>2)] = codeUnit; + outPtr += 4; + if (outPtr + 4 > endPtr) break; + } + // Null-terminate the pointer to the HEAP. + HEAP32[((outPtr)>>2)] = 0; + return outPtr - startPtr; + }; + + var lengthBytesUTF32 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var codeUnit = str.charCodeAt(i); + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate. + len += 4; + } + + return len; + }; + var __embind_register_std_wstring = (rawType, charSize, name) => { + name = readLatin1String(name); + var decodeString, encodeString, readCharAt, lengthBytesUTF; + if (charSize === 2) { + decodeString = UTF16ToString; + encodeString = stringToUTF16; + lengthBytesUTF = lengthBytesUTF16; + readCharAt = (pointer) => HEAPU16[((pointer)>>1)]; + } else if (charSize === 4) { + decodeString = UTF32ToString; + encodeString = stringToUTF32; + lengthBytesUTF = lengthBytesUTF32; + readCharAt = (pointer) => HEAPU32[((pointer)>>2)]; + } + registerType(rawType, { + name, + 'fromWireType': (value) => { + // Code mostly taken from _embind_register_std_string fromWireType + var length = HEAPU32[((value)>>2)]; + var str; + + var decodeStartPtr = value + 4; + // Looping here to support possible embedded '0' bytes + for (var i = 0; i <= length; ++i) { + var currentBytePtr = value + 4 + i * charSize; + if (i == length || readCharAt(currentBytePtr) == 0) { + var maxReadBytes = currentBytePtr - decodeStartPtr; + var stringSegment = decodeString(decodeStartPtr, maxReadBytes); + if (str === undefined) { + str = stringSegment; + } else { + str += String.fromCharCode(0); + str += stringSegment; + } + decodeStartPtr = currentBytePtr + charSize; + } + } + + _free(value); + + return str; + }, + 'toWireType': (destructors, value) => { + if (!(typeof value == 'string')) { + throwBindingError(`Cannot pass non-string to C++ string type ${name}`); + } + + // assumes POINTER_SIZE alignment + var length = lengthBytesUTF(value); + var ptr = _malloc(4 + length + charSize); + HEAPU32[((ptr)>>2)] = length / charSize; + + encodeString(value, ptr + 4, length + charSize); + + if (destructors !== null) { + destructors.push(_free, ptr); + } + return ptr; + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, + destructorFunction(ptr) { + _free(ptr); + } + }); + }; + + + var __embind_register_void = (rawType, name) => { + name = readLatin1String(name); + registerType(rawType, { + isVoid: true, // void return values can be optimized out sometimes + name, + 'argPackAdvance': 0, + 'fromWireType': () => undefined, + // TODO: assert if anything else is given? + 'toWireType': (destructors, o) => undefined, + }); + }; + + var __emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); + + var emval_methodCallers = []; + + var __emval_call = (caller, handle, destructorsRef, args) => { + caller = emval_methodCallers[caller]; + handle = Emval.toValue(handle); + return caller(null, handle, destructorsRef, args); + }; + + + + var emval_symbols = { + }; + + var getStringOrSymbol = (address) => { + var symbol = emval_symbols[address]; + if (symbol === undefined) { + return readLatin1String(address); + } + return symbol; + }; + + var emval_get_global = () => { + if (typeof globalThis == 'object') { + return globalThis; + } + function testGlobal(obj) { + obj['$$$embind_global$$$'] = obj; + var success = typeof $$$embind_global$$$ == 'object' && obj['$$$embind_global$$$'] == obj; + if (!success) { + delete obj['$$$embind_global$$$']; + } + return success; + } + if (typeof $$$embind_global$$$ == 'object') { + return $$$embind_global$$$; + } + if (typeof global == 'object' && testGlobal(global)) { + $$$embind_global$$$ = global; + } else if (typeof self == 'object' && testGlobal(self)) { + $$$embind_global$$$ = self; // This works for both "window" and "self" (Web Workers) global objects + } + if (typeof $$$embind_global$$$ == 'object') { + return $$$embind_global$$$; + } + throw Error('unable to get global object.'); + }; + var __emval_get_global = (name) => { + if (name===0) { + return Emval.toHandle(emval_get_global()); + } else { + name = getStringOrSymbol(name); + return Emval.toHandle(emval_get_global()[name]); + } + }; + + var emval_addMethodCaller = (caller) => { + var id = emval_methodCallers.length; + emval_methodCallers.push(caller); + return id; + }; + + + + var requireRegisteredType = (rawType, humanName) => { + var impl = registeredTypes[rawType]; + if (undefined === impl) { + throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`); + } + return impl; + }; + var emval_lookupTypes = (argCount, argTypes) => { + var a = new Array(argCount); + for (var i = 0; i < argCount; ++i) { + a[i] = requireRegisteredType(HEAPU32[(((argTypes)+(i * 4))>>2)], + "parameter " + i); + } + return a; + }; + + + var reflectConstruct = Reflect.construct; + + var emval_returnValue = (returnType, destructorsRef, handle) => { + var destructors = []; + var result = returnType['toWireType'](destructors, handle); + if (destructors.length) { + // void, primitives and any other types w/o destructors don't need to allocate a handle + HEAPU32[((destructorsRef)>>2)] = Emval.toHandle(destructors); + } + return result; + }; + var __emval_get_method_caller = (argCount, argTypes, kind) => { + var types = emval_lookupTypes(argCount, argTypes); + var retType = types.shift(); + argCount--; // remove the shifted off return type + + var argN = new Array(argCount); + var invokerFunction = (obj, func, destructorsRef, args) => { + var offset = 0; + for (var i = 0; i < argCount; ++i) { + argN[i] = types[i]['readValueFromPointer'](args + offset); + offset += types[i]['argPackAdvance']; + } + var rv = kind === /* CONSTRUCTOR */ 1 ? reflectConstruct(func, argN) : func.apply(obj, argN); + return emval_returnValue(retType, destructorsRef, rv); + }; + var functionName = `methodCaller<(${types.map(t => t.name).join(', ')}) => ${retType.name}>`; + return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction)); + }; + + + + var __emval_run_destructors = (handle) => { + var destructors = Emval.toValue(handle); + runDestructors(destructors); + __emval_decref(handle); + }; + + var _abort = () => { + abort('native code called abort()'); + }; + + var getHeapMax = () => + // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate + // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side + // for any code that deals with heap sizes, which would require special + // casing all heap size related code to treat 0 specially. + 2147483648; + + var growMemory = (size) => { + var b = wasmMemory.buffer; + var pages = (size - b.byteLength + 65535) / 65536; + try { + // round size grow request up to wasm page size (fixed 64KB per spec) + wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size + updateMemoryViews(); + return 1 /*success*/; + } catch(e) { + err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`); + } + // implicit 0 return to save code size (caller will cast "undefined" into 0 + // anyhow) + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + requestedSize >>>= 0; + // With multithreaded builds, races can happen (another thread might increase the size + // in between), so return a failure, and let the caller retry. + assert(requestedSize > oldSize); + + // Memory resize rules: + // 1. Always increase heap size to at least the requested size, rounded up + // to next page multiple. + // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap + // geometrically: increase the heap size according to + // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most + // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB). + // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap + // linearly: increase the heap size by at least + // MEMORY_GROWTH_LINEAR_STEP bytes. + // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by + // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest + // 4. If we were unable to allocate as much memory, it may be due to + // over-eager decision to excessively reserve due to (3) above. + // Hence if an allocation fails, cut down on the amount of excess + // growth, in an attempt to succeed to perform a smaller allocation. + + // A limit is set for how much we can grow. We should not exceed that + // (the wasm binary specifies it, so if we tried, we'd fail anyhow). + var maxHeapSize = getHeapMax(); + if (requestedSize > maxHeapSize) { + err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`); + return false; + } + + var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple; + + // Loop through potential heap size increases. If we attempt a too eager + // reservation that fails, cut down on the attempted size and reserve a + // smaller bump instead. (max 3 times, chosen somewhat arbitrarily) + for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { + var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth + // but limit overreserving (default to capping at +96MB overgrowth at most) + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 ); + + var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); + + var replacement = growMemory(newSize); + if (replacement) { + + return true; + } + } + err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`); + return false; + }; + + var SYSCALLS = { + varargs:undefined, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + }; + var _fd_close = (fd) => { + abort('fd_close called without SYSCALLS_REQUIRE_FILESYSTEM'); + }; + + var convertI32PairToI53Checked = (lo, hi) => { + assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32 + assert(hi === (hi|0)); // hi should be a i32 + return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; + }; + function _fd_seek(fd,offset_low, offset_high,whence,newOffset) { + var offset = convertI32PairToI53Checked(offset_low, offset_high); + + + return 70; + ; + } + + var printCharBuffers = [null,[],[]]; + + var printChar = (stream, curr) => { + var buffer = printCharBuffers[stream]; + assert(buffer); + if (curr === 0 || curr === 10) { + (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); + buffer.length = 0; + } else { + buffer.push(curr); + } + }; + + var flush_NO_FILESYSTEM = () => { + // flush anything remaining in the buffers during shutdown + _fflush(0); + if (printCharBuffers[1].length) printChar(1, 10); + if (printCharBuffers[2].length) printChar(2, 10); + }; + + + var _fd_write = (fd, iov, iovcnt, pnum) => { + // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 + var num = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + for (var j = 0; j < len; j++) { + printChar(fd, HEAPU8[ptr+j]); + } + num += len; + } + HEAPU32[((pnum)>>2)] = num; + return 0; + }; +embind_init_charCodes(); +BindingError = Module['BindingError'] = class BindingError extends Error { constructor(message) { super(message); this.name = 'BindingError'; }}; +InternalError = Module['InternalError'] = class InternalError extends Error { constructor(message) { super(message); this.name = 'InternalError'; }}; +init_emval();; +UnboundTypeError = Module['UnboundTypeError'] = extendError(Error, 'UnboundTypeError');; +function checkIncomingModuleAPI() { + ignoredModuleProp('fetchSettings'); +} +var wasmImports = { + /** @export */ + __assert_fail: ___assert_fail, + /** @export */ + __cxa_throw: ___cxa_throw, + /** @export */ + _embind_register_bigint: __embind_register_bigint, + /** @export */ + _embind_register_bool: __embind_register_bool, + /** @export */ + _embind_register_emval: __embind_register_emval, + /** @export */ + _embind_register_float: __embind_register_float, + /** @export */ + _embind_register_function: __embind_register_function, + /** @export */ + _embind_register_integer: __embind_register_integer, + /** @export */ + _embind_register_memory_view: __embind_register_memory_view, + /** @export */ + _embind_register_std_string: __embind_register_std_string, + /** @export */ + _embind_register_std_wstring: __embind_register_std_wstring, + /** @export */ + _embind_register_void: __embind_register_void, + /** @export */ + _emscripten_memcpy_js: __emscripten_memcpy_js, + /** @export */ + _emval_call: __emval_call, + /** @export */ + _emval_decref: __emval_decref, + /** @export */ + _emval_get_global: __emval_get_global, + /** @export */ + _emval_get_method_caller: __emval_get_method_caller, + /** @export */ + _emval_run_destructors: __emval_run_destructors, + /** @export */ + abort: _abort, + /** @export */ + emscripten_resize_heap: _emscripten_resize_heap, + /** @export */ + fd_close: _fd_close, + /** @export */ + fd_seek: _fd_seek, + /** @export */ + fd_write: _fd_write +}; +var wasmExports = createWasm(); +var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors', 0); +var ___getTypeName = createExportWrapper('__getTypeName', 1); +var _free = createExportWrapper('free', 1); +var _malloc = createExportWrapper('malloc', 1); +var _fflush = createExportWrapper('fflush', 1); +var _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports['emscripten_stack_init'])(); +var _emscripten_stack_get_free = () => (_emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'])(); +var _emscripten_stack_get_base = () => (_emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'])(); +var _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'])(); +var __emscripten_stack_restore = (a0) => (__emscripten_stack_restore = wasmExports['_emscripten_stack_restore'])(a0); +var __emscripten_stack_alloc = (a0) => (__emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc'])(a0); +var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])(); +var ___cxa_increment_exception_refcount = createExportWrapper('__cxa_increment_exception_refcount', 1); +var ___cxa_is_pointer_type = createExportWrapper('__cxa_is_pointer_type', 1); +var dynCall_jiji = Module['dynCall_jiji'] = createExportWrapper('dynCall_jiji', 5); + + +// include: postamble.js +// === Auto-generated postamble setup entry stuff === + +var missingLibrarySymbols = [ + 'writeI53ToI64', + 'writeI53ToI64Clamped', + 'writeI53ToI64Signaling', + 'writeI53ToU64Clamped', + 'writeI53ToU64Signaling', + 'readI53FromI64', + 'readI53FromU64', + 'convertI32PairToI53', + 'convertU32PairToI53', + 'stackAlloc', + 'getTempRet0', + 'setTempRet0', + 'zeroMemory', + 'exitJS', + 'isLeapYear', + 'ydayFromDate', + 'arraySum', + 'addDays', + 'inetPton4', + 'inetNtop4', + 'inetPton6', + 'inetNtop6', + 'readSockaddr', + 'writeSockaddr', + 'initRandomFill', + 'randomFill', + 'emscriptenLog', + 'readEmAsmArgs', + 'jstoi_q', + 'getExecutableName', + 'listenOnce', + 'autoResumeAudioContext', + 'handleException', + 'keepRuntimeAlive', + 'runtimeKeepalivePush', + 'runtimeKeepalivePop', + 'callUserCallback', + 'maybeExit', + 'asmjsMangle', + 'asyncLoad', + 'alignMemory', + 'mmapAlloc', + 'HandleAllocator', + 'getNativeTypeSize', + 'STACK_SIZE', + 'STACK_ALIGN', + 'POINTER_SIZE', + 'ASSERTIONS', + 'getCFunc', + 'ccall', + 'cwrap', + 'uleb128Encode', + 'sigToWasmTypes', + 'generateFuncType', + 'convertJsFunctionToWasm', + 'getEmptyTableSlot', + 'updateTableMap', + 'getFunctionAddress', + 'addFunction', + 'removeFunction', + 'reallyNegative', + 'unSign', + 'strLen', + 'reSign', + 'formatString', + 'intArrayFromString', + 'intArrayToString', + 'AsciiToString', + 'stringToAscii', + 'stringToNewUTF8', + 'stringToUTF8OnStack', + 'writeArrayToMemory', + 'registerKeyEventCallback', + 'maybeCStringToJsString', + 'findEventTarget', + 'getBoundingClientRect', + 'fillMouseEventData', + 'registerMouseEventCallback', + 'registerWheelEventCallback', + 'registerUiEventCallback', + 'registerFocusEventCallback', + 'fillDeviceOrientationEventData', + 'registerDeviceOrientationEventCallback', + 'fillDeviceMotionEventData', + 'registerDeviceMotionEventCallback', + 'screenOrientation', + 'fillOrientationChangeEventData', + 'registerOrientationChangeEventCallback', + 'fillFullscreenChangeEventData', + 'registerFullscreenChangeEventCallback', + 'JSEvents_requestFullscreen', + 'JSEvents_resizeCanvasForFullscreen', + 'registerRestoreOldStyle', + 'hideEverythingExceptGivenElement', + 'restoreHiddenElements', + 'setLetterbox', + 'softFullscreenResizeWebGLRenderTarget', + 'doRequestFullscreen', + 'fillPointerlockChangeEventData', + 'registerPointerlockChangeEventCallback', + 'registerPointerlockErrorEventCallback', + 'requestPointerLock', + 'fillVisibilityChangeEventData', + 'registerVisibilityChangeEventCallback', + 'registerTouchEventCallback', + 'fillGamepadEventData', + 'registerGamepadEventCallback', + 'registerBeforeUnloadEventCallback', + 'fillBatteryEventData', + 'battery', + 'registerBatteryEventCallback', + 'setCanvasElementSize', + 'getCanvasElementSize', + 'jsStackTrace', + 'getCallstack', + 'convertPCtoSourceLocation', + 'getEnvStrings', + 'checkWasiClock', + 'wasiRightsToMuslOFlags', + 'wasiOFlagsToMuslOFlags', + 'createDyncallWrapper', + 'safeSetTimeout', + 'setImmediateWrapped', + 'clearImmediateWrapped', + 'polyfillSetImmediate', + 'getPromise', + 'makePromise', + 'idsToPromises', + 'makePromiseCallback', + 'findMatchingCatch', + 'Browser_asyncPrepareDataCounter', + 'setMainLoop', + 'getSocketFromFD', + 'getSocketAddress', + 'heapObjectForWebGLType', + 'toTypedArrayIndex', + 'webgl_enable_ANGLE_instanced_arrays', + 'webgl_enable_OES_vertex_array_object', + 'webgl_enable_WEBGL_draw_buffers', + 'webgl_enable_WEBGL_multi_draw', + 'emscriptenWebGLGet', + 'computeUnpackAlignedImageSize', + 'colorChannelsInGlTextureFormat', + 'emscriptenWebGLGetTexPixelData', + 'emscriptenWebGLGetUniform', + 'webglGetUniformLocation', + 'webglPrepareUniformLocationsBeforeFirstUse', + 'webglGetLeftBracePos', + 'emscriptenWebGLGetVertexAttrib', + '__glGetActiveAttribOrUniform', + 'writeGLArray', + 'registerWebGlEventCallback', + 'runAndAbortIfError', + 'ALLOC_NORMAL', + 'ALLOC_STACK', + 'allocate', + 'writeStringToMemory', + 'writeAsciiToMemory', + 'setErrNo', + 'demangle', + 'stackTrace', + 'getFunctionArgsName', + 'createJsInvokerSignature', + 'createJsInvoker', + 'init_embind', + 'getBasestPointer', + 'registerInheritedInstance', + 'unregisterInheritedInstance', + 'getInheritedInstance', + 'getInheritedInstanceCount', + 'getLiveInheritedInstances', + 'enumReadValueFromPointer', + 'genericPointerToWireType', + 'constNoSmartPtrRawPointerToWireType', + 'nonConstNoSmartPtrRawPointerToWireType', + 'init_RegisteredPointer', + 'RegisteredPointer', + 'RegisteredPointer_fromWireType', + 'runDestructor', + 'releaseClassHandle', + 'detachFinalizer', + 'attachFinalizer', + 'makeClassHandle', + 'init_ClassHandle', + 'ClassHandle', + 'throwInstanceAlreadyDeleted', + 'flushPendingDeletes', + 'setDelayFunction', + 'RegisteredClass', + 'shallowCopyInternalPointer', + 'downcastPointer', + 'upcastPointer', + 'validateThis', + 'char_0', + 'char_9', + 'makeLegalFunctionName', +]; +missingLibrarySymbols.forEach(missingLibrarySymbol) + +var unexportedSymbols = [ + 'run', + 'addOnPreRun', + 'addOnInit', + 'addOnPreMain', + 'addOnExit', + 'addOnPostRun', + 'addRunDependency', + 'removeRunDependency', + 'FS_createFolder', + 'FS_createPath', + 'FS_createLazyFile', + 'FS_createLink', + 'FS_createDevice', + 'FS_readFile', + 'out', + 'err', + 'callMain', + 'abort', + 'wasmMemory', + 'wasmExports', + 'writeStackCookie', + 'checkStackCookie', + 'convertI32PairToI53Checked', + 'stackSave', + 'stackRestore', + 'ptrToString', + 'getHeapMax', + 'growMemory', + 'ENV', + 'MONTH_DAYS_REGULAR', + 'MONTH_DAYS_LEAP', + 'MONTH_DAYS_REGULAR_CUMULATIVE', + 'MONTH_DAYS_LEAP_CUMULATIVE', + 'ERRNO_CODES', + 'ERRNO_MESSAGES', + 'DNS', + 'Protocols', + 'Sockets', + 'timers', + 'warnOnce', + 'readEmAsmArgsArray', + 'jstoi_s', + 'dynCallLegacy', + 'getDynCaller', + 'dynCall', + 'wasmTable', + 'noExitRuntime', + 'freeTableIndexes', + 'functionsInTableMap', + 'setValue', + 'getValue', + 'PATH', + 'PATH_FS', + 'UTF8ArrayToString', + 'UTF8ToString', + 'stringToUTF8Array', + 'stringToUTF8', + 'lengthBytesUTF8', + 'UTF16ToString', + 'stringToUTF16', + 'lengthBytesUTF16', + 'UTF32ToString', + 'stringToUTF32', + 'lengthBytesUTF32', + 'JSEvents', + 'specialHTMLTargets', + 'findCanvasEventTarget', + 'currentFullscreenStrategy', + 'restoreOldWindowedStyle', + 'UNWIND_CACHE', + 'ExitStatus', + 'flush_NO_FILESYSTEM', + 'promiseMap', + 'uncaughtExceptionCount', + 'exceptionLast', + 'exceptionCaught', + 'ExceptionInfo', + 'Browser', + 'getPreloadedImageData__data', + 'wget', + 'SYSCALLS', + 'tempFixedLengthArray', + 'miniTempWebGLFloatBuffers', + 'miniTempWebGLIntBuffers', + 'GL', + 'AL', + 'GLUT', + 'EGL', + 'GLEW', + 'IDBStore', + 'SDL', + 'SDL_gfx', + 'allocateUTF8', + 'allocateUTF8OnStack', + 'InternalError', + 'BindingError', + 'throwInternalError', + 'throwBindingError', + 'registeredTypes', + 'awaitingDependencies', + 'typeDependencies', + 'tupleRegistrations', + 'structRegistrations', + 'sharedRegisterType', + 'whenDependentTypesAreResolved', + 'embind_charCodes', + 'embind_init_charCodes', + 'readLatin1String', + 'getTypeName', + 'getFunctionName', + 'heap32VectorToArray', + 'requireRegisteredType', + 'usesDestructorStack', + 'UnboundTypeError', + 'PureVirtualError', + 'GenericWireTypeSize', + 'EmValType', + 'throwUnboundTypeError', + 'ensureOverloadTable', + 'exposePublicSymbol', + 'replacePublicSymbol', + 'extendError', + 'createNamedFunction', + 'embindRepr', + 'registeredInstances', + 'registeredPointers', + 'registerType', + 'integerReadValueFromPointer', + 'floatReadValueFromPointer', + 'readPointer', + 'runDestructors', + 'craftInvokerFunction', + 'embind__requireFunction', + 'finalizationRegistry', + 'detachFinalizer_deps', + 'deletionQueue', + 'delayFunction', + 'emval_freelist', + 'emval_handles', + 'emval_symbols', + 'init_emval', + 'count_emval_handles', + 'getStringOrSymbol', + 'Emval', + 'emval_get_global', + 'emval_returnValue', + 'emval_lookupTypes', + 'emval_methodCallers', + 'emval_addMethodCaller', + 'reflectConstruct', +]; +unexportedSymbols.forEach(unexportedRuntimeSymbol); + + + +var calledRun; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun) run(); + if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +}; + +function stackCheckInit() { + // This is normally called automatically during __wasm_call_ctors but need to + // get these values before even running any of the ctors so we call it redundantly + // here. + _emscripten_stack_init(); + // TODO(sbc): Move writeStackCookie to native to to avoid this. + writeStackCookie(); +} + +function run() { + + if (runDependencies > 0) { + return; + } + + stackCheckInit(); + + preRun(); + + // a preRun added a dependency, run will be called later + if (runDependencies > 0) { + return; + } + + function doRun() { + // run may have just been called through dependencies being fulfilled just in this very frame, + // or while the async setStatus time below was happening + if (calledRun) return; + calledRun = true; + Module['calledRun'] = true; + + if (ABORT) return; + + initRuntime(); + + readyPromiseResolve(Module); + if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); + + assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'); + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + doRun(); + }, 1); + } else + { + doRun(); + } + checkStackCookie(); +} + +function checkUnflushedContent() { + // Compiler settings do not allow exiting the runtime, so flushing + // the streams is not possible. but in ASSERTIONS mode we check + // if there was something to flush, and if so tell the user they + // should request that the runtime be exitable. + // Normally we would not even include flush() at all, but in ASSERTIONS + // builds we do so just for this check, and here we see if there is any + // content to flush, that is, we check if there would have been + // something a non-ASSERTIONS build would have not seen. + // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0 + // mode (which has its own special function for this; otherwise, all + // the code is inside libc) + var oldOut = out; + var oldErr = err; + var has = false; + out = err = (x) => { + has = true; + } + try { // it doesn't matter if it fails + flush_NO_FILESYSTEM(); + } catch(e) {} + out = oldOut; + err = oldErr; + if (has) { + warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.'); + warnOnce('(this may also be due to not including full filesystem support - try building with -sFORCE_FILESYSTEM)'); + } +} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +run(); + +// end include: postamble.js + + + + return readyPromise +} +); +})(); +export default Module; \ No newline at end of file diff --git a/packages/jxr/codec/dec/jxr_dec.wasm b/packages/jxr/codec/dec/jxr_dec.wasm new file mode 100755 index 0000000..298c335 Binary files /dev/null and b/packages/jxr/codec/dec/jxr_dec.wasm differ diff --git a/packages/jxr/codec/package.json b/packages/jxr/codec/package.json new file mode 100644 index 0000000..1105641 --- /dev/null +++ b/packages/jxr/codec/package.json @@ -0,0 +1,6 @@ +{ + "scripts": { + "build": "docker run --rm -v \"$PWD\":/src alpine sh -c \"find /src -name '*.o' -delete\" && EMSDK_VERSION=3.1.57 DEFAULT_CFLAGS='-Oz -flto' ../../../tools/build-cpp.sh" + }, + "type": "module" +} diff --git a/packages/jxr/codec/pre.js b/packages/jxr/codec/pre.js new file mode 100644 index 0000000..073dd63 --- /dev/null +++ b/packages/jxr/codec/pre.js @@ -0,0 +1,24 @@ +const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; +const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; +const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; + +if (isRunningInCloudFlareWorkers || isRunningInNode) { + if (!globalThis.ImageData) { + // Simple Polyfill for ImageData Object + globalThis.ImageData = class ImageData { + constructor(data, width, height) { + this.data = data; + this.width = width; + this.height = height; + } + }; + } + + if (import.meta.url === undefined) { + import.meta.url = 'https://localhost'; + } + + if (typeof self !== 'undefined' && self.location === undefined) { + self.location = { href: '' }; + } +} diff --git a/packages/jxr/decode.ts b/packages/jxr/decode.ts new file mode 100644 index 0000000..64b49ac --- /dev/null +++ b/packages/jxr/decode.ts @@ -0,0 +1,42 @@ +import type { JXRModule } from './codec/dec/jxr_dec.js'; +import { initEmscriptenModule } from './utils.js'; + +import jxr_dec from './codec/dec/jxr_dec.js'; + +let emscriptenModule: Promise; + +export async function init( + moduleOptionOverrides?: Partial, +): Promise; +export async function init( + module?: WebAssembly.Module, + moduleOptionOverrides?: Partial, +): Promise { + let actualModule: WebAssembly.Module | undefined = module; + let actualOptions: Partial | undefined = + moduleOptionOverrides; + + if (arguments.length === 1 && !(module instanceof WebAssembly.Module)) { + actualModule = undefined; + actualOptions = module as unknown as Partial; + } + + emscriptenModule = initEmscriptenModule( + jxr_dec, + actualModule, + actualOptions, + ); +} + +export default async function decode( + buffer: ArrayBuffer, +): Promise { + if (!emscriptenModule) { + init(); + } + + const module = await emscriptenModule; + const result = module.decode(buffer); + if (!result) throw new Error('Decoding error'); + return result; +} diff --git a/packages/jxr/dist/.npmignore b/packages/jxr/dist/.npmignore new file mode 100644 index 0000000..9d32211 --- /dev/null +++ b/packages/jxr/dist/.npmignore @@ -0,0 +1,6 @@ +*.cpp +Makefile +node_modules +codec/*package.json +*.d.ts.map +tsconfig.tsbuildinfo diff --git a/packages/jxr/dist/LICENSE b/packages/jxr/dist/LICENSE new file mode 100644 index 0000000..64bfa05 --- /dev/null +++ b/packages/jxr/dist/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2023] jamsinclair + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/jxr/dist/README.md b/packages/jxr/dist/README.md new file mode 100644 index 0000000..b741340 --- /dev/null +++ b/packages/jxr/dist/README.md @@ -0,0 +1,57 @@ +# @jsquash/jxr + +[![npm version](https://badge.fury.io/js/@jsquash%2Fjxr.svg)](https://badge.fury.io/js/@jsquash%2Fjxr) + +An easy way to decode JPEG XR images in the browser with WebAssembly. + +Uses the [`jxrlib`](https://github.com/bvibber/jpegxr) library. + +A [jSquash](https://github.com/jamsinclair/jSquash) package. + +## Installation + +```shell +npm install --save @jsquash/jxr +``` + +## Usage + +Note: You will need to either manually include the wasm files from the codec directory or use a bundler like WebPack or Rollup to include them in your app/server. + +### `decode(data: ArrayBuffer): Promise` + +Decodes JPEG XR binary data to `ImageData`. + +#### Example + +```js +import { decode } from '@jsquash/jxr'; + +const imageBuffer = await fetch('/example.jxr').then((res) => res.arrayBuffer()); +const imageData = await decode(imageBuffer); +``` + +## Manual WASM initialisation (not recommended) + +The `decode` module exports an `init` function that can be used to manually load the wasm module. + +```js +import decode, { init as initJXRDecode } from '@jsquash/jxr/decode'; + +initJXRDecode(WASM_MODULE); +const image = await fetch('./image.jxr').then((res) => res.arrayBuffer()).then(decode); +``` + +You can also pass custom options to the `init` function to customise the behaviour of the module. See the [Emscripten documentation](https://emscripten.org/docs/api_reference/module.html#Module) for more information. + +```js +import decode, { init as initJXRDecode } from '@jsquash/jxr/decode'; + +initJXRDecode(null, { + locateFile: (path, prefix) => `https://example.com/${prefix}/${path}`, +}); +``` + +## Known Issues + +See [jSquash Project README](https://github.com/jamsinclair/jSquash#known-issues) diff --git a/packages/jxr/dist/codec/Makefile b/packages/jxr/dist/codec/Makefile new file mode 100644 index 0000000..f130719 --- /dev/null +++ b/packages/jxr/dist/codec/Makefile @@ -0,0 +1,111 @@ +CODEC_URL = https://github.com/bvibber/jpegxr/archive/refs/tags/0.3.1.tar.gz +CODEC_PACKAGE = node_modules/jpegxr.tar.gz +CODEC_DIR = node_modules/jpegxr +JXRLIB_DIR = $(CODEC_DIR)/jxrlib +EXTRACTED_STAMP = $(CODEC_DIR)/.extracted + +ENVIRONMENT = web,worker +PRE_JS = pre.js + +OUT_DEC_JS = dec/jxr_dec.js +OUT_DEC_CPP = dec/jxr_dec.cpp +OUT_DEC_WASM = dec/jxr_dec.wasm + +TOTAL_STACK = 5242880 +INITIAL_MEMORY_SIZE = 16777216 + +CODEC_SOURCES = \ + $(JXRLIB_DIR)/image/sys/adapthuff.c \ + $(JXRLIB_DIR)/image/sys/image.c \ + $(JXRLIB_DIR)/image/sys/strcodec.c \ + $(JXRLIB_DIR)/image/sys/strPredQuant.c \ + $(JXRLIB_DIR)/image/sys/strTransform.c \ + $(JXRLIB_DIR)/image/sys/perfTimerANSI.c \ + $(JXRLIB_DIR)/image/decode/decode.c \ + $(JXRLIB_DIR)/image/decode/postprocess.c \ + $(JXRLIB_DIR)/image/decode/segdec.c \ + $(JXRLIB_DIR)/image/decode/strdec.c \ + $(JXRLIB_DIR)/image/decode/strInvTransform.c \ + $(JXRLIB_DIR)/image/decode/strPredQuantDec.c \ + $(JXRLIB_DIR)/image/decode/JXRTranscode.c \ + $(JXRLIB_DIR)/jxrgluelib/JXRGlue.c \ + $(JXRLIB_DIR)/jxrgluelib/JXRGlueJxr.c \ + $(JXRLIB_DIR)/jxrgluelib/JXRGluePFC.c \ + $(JXRLIB_DIR)/jxrgluelib/JXRMeta.c + +CODEC_OBJECTS = $(CODEC_SOURCES:.c=.o) +WRAPPER_OBJECT = $(OUT_DEC_CPP:.cpp=.o) + +JXR_INCLUDE_FLAGS = \ + -D__ANSI__ \ + -DDISABLE_PERF_MEASUREMENT \ + -I $(JXRLIB_DIR)/jxrgluelib \ + -I $(JXRLIB_DIR)/common/include \ + -I $(JXRLIB_DIR)/image/sys \ + -Wno-constant-conversion \ + -Wno-unused-const-variable \ + -Wno-deprecated-declarations \ + -Wno-comment \ + -Wno-unused-value \ + -Wno-unused-function \ + -Wno-unknown-pragmas \ + -Wno-extra-tokens \ + -Wno-missing-field-initializers \ + -Wno-shift-negative-value \ + -Wno-dangling-else \ + -Wno-sign-compare \ + -Wno-strict-aliasing \ + -Wno-implicit-fallthrough \ + -Wno-endif-labels \ + -Wno-parentheses \ + -Wno-misleading-indentation \ + -Wno-unused-but-set-variable + +.PHONY: all clean + +all: $(OUT_DEC_JS) + +$(OUT_DEC_JS): $(WRAPPER_OBJECT) $(CODEC_OBJECTS) + $(CXX) \ + $(LDFLAGS) \ + -O0 \ + --pre-js $(PRE_JS) \ + --bind \ + -s ENVIRONMENT=$(ENVIRONMENT) \ + -s EXPORT_ES6=1 \ + -s DYNAMIC_EXECUTION=0 \ + -s ALLOW_MEMORY_GROWTH=1 \ + -s MODULARIZE=1 \ + -s TOTAL_STACK=$(TOTAL_STACK) \ + -s INITIAL_MEMORY=$(INITIAL_MEMORY_SIZE) \ + -o $@ \ + $(WRAPPER_OBJECT) $(CODEC_OBJECTS) + +$(OUT_DEC_JS): $(EXTRACTED_STAMP) + +$(CODEC_OBJECTS): %.o: $(EXTRACTED_STAMP) + $(CC) -c \ + $(CFLAGS) \ + $(JXR_INCLUDE_FLAGS) \ + -o $@ \ + $(@:.o=.c) + +$(WRAPPER_OBJECT): %.o: %.cpp $(EXTRACTED_STAMP) + $(CXX) -c \ + $(CXXFLAGS) \ + $(JXR_INCLUDE_FLAGS) \ + -o $@ \ + $< + +$(EXTRACTED_STAMP): $(CODEC_PACKAGE) + mkdir -p $(CODEC_DIR) + tar xzm --strip 1 -C $(CODEC_DIR) -f $(CODEC_PACKAGE) + touch $@ + +$(CODEC_PACKAGE): + mkdir -p $(@D) + curl -sL $(CODEC_URL) -o $@ + +clean: + $(RM) $(WRAPPER_OBJECT) $(OUT_DEC_JS) $(OUT_DEC_WASM) + $(RM) $(CODEC_OBJECTS) diff --git a/packages/jxr/dist/codec/dec/jxr_dec.cpp b/packages/jxr/dist/codec/dec/jxr_dec.cpp new file mode 100644 index 0000000..3517d5c --- /dev/null +++ b/packages/jxr/dist/codec/dec/jxr_dec.cpp @@ -0,0 +1,948 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "JXRGlue.h" + +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +using namespace emscripten; + +thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray"); +thread_local const val ImageData = val::global("ImageData"); + +namespace { +enum class OutputKind { + RGBA8, + PRGBA8, + BGRA8, + PBGRA8, + RGB8, + BGR8, + RGBX8, + BGRX8, + GRAY8, + RGBA16, + PRGBA16, + RGB16, + RGB16X, + GRAY16, + RGBAFloat, + PRGBAFloat, + RGBFloat, + RGBFloatX, + GRAYFloat, + RGBAHalf, + RGBHalf, + RGBHalfX, + GRAYHalf, + RGBAFixed16, + RGBFixed16, + RGBFixed16X, + GRAYFixed16, + RGBAFixed32, + RGBFixed32, + RGBFixed32X, + GRAYFixed32, + RGB101010, + RGBE, +}; + +struct DecodeTarget { + PKPixelFormatGUID guid; + OutputKind kind; + int bytes_per_pixel; +}; + +struct ToneMapSettings { + bool enabled; + float white; +}; + +constexpr size_t kToneMapSampleCount = 16384; +constexpr float kToneMapWhitePercentile = 0.99f; + +const DecodeTarget kTargets[] = { + {GUID_PKPixelFormat32bppRGBA, OutputKind::RGBA8, 4}, + {GUID_PKPixelFormat32bppPRGBA, OutputKind::PRGBA8, 4}, + {GUID_PKPixelFormat32bppBGRA, OutputKind::BGRA8, 4}, + {GUID_PKPixelFormat32bppPBGRA, OutputKind::PBGRA8, 4}, + {GUID_PKPixelFormat24bppRGB, OutputKind::RGB8, 3}, + {GUID_PKPixelFormat24bppBGR, OutputKind::BGR8, 3}, + {GUID_PKPixelFormat32bppRGB, OutputKind::RGBX8, 4}, + {GUID_PKPixelFormat32bppBGR, OutputKind::BGRX8, 4}, + {GUID_PKPixelFormat8bppGray, OutputKind::GRAY8, 1}, + {GUID_PKPixelFormat64bppRGBA, OutputKind::RGBA16, 8}, + {GUID_PKPixelFormat64bppPRGBA, OutputKind::PRGBA16, 8}, + {GUID_PKPixelFormat48bppRGB, OutputKind::RGB16, 6}, + {GUID_PKPixelFormat64bppRGBFixedPoint, OutputKind::RGBFixed16X, 8}, + {GUID_PKPixelFormat16bppGray, OutputKind::GRAY16, 2}, + {GUID_PKPixelFormat128bppRGBAFloat, OutputKind::RGBAFloat, 16}, + {GUID_PKPixelFormat128bppPRGBAFloat, OutputKind::PRGBAFloat, 16}, + {GUID_PKPixelFormat96bppRGBFloat, OutputKind::RGBFloat, 12}, + {GUID_PKPixelFormat128bppRGBFloat, OutputKind::RGBFloatX, 16}, + {GUID_PKPixelFormat32bppGrayFloat, OutputKind::GRAYFloat, 4}, + {GUID_PKPixelFormat64bppRGBAHalf, OutputKind::RGBAHalf, 8}, + {GUID_PKPixelFormat48bppRGBHalf, OutputKind::RGBHalf, 6}, + {GUID_PKPixelFormat64bppRGBHalf, OutputKind::RGBHalfX, 8}, + {GUID_PKPixelFormat16bppGrayHalf, OutputKind::GRAYHalf, 2}, + {GUID_PKPixelFormat64bppRGBAFixedPoint, OutputKind::RGBAFixed16, 8}, + {GUID_PKPixelFormat48bppRGBFixedPoint, OutputKind::RGBFixed16, 6}, + {GUID_PKPixelFormat16bppGrayFixedPoint, OutputKind::GRAYFixed16, 2}, + {GUID_PKPixelFormat128bppRGBAFixedPoint, OutputKind::RGBAFixed32, 16}, + {GUID_PKPixelFormat96bppRGBFixedPoint, OutputKind::RGBFixed32, 12}, + {GUID_PKPixelFormat128bppRGBFixedPoint, OutputKind::RGBFixed32X, 16}, + {GUID_PKPixelFormat32bppGrayFixedPoint, OutputKind::GRAYFixed32, 4}, + {GUID_PKPixelFormat32bppRGB101010, OutputKind::RGB101010, 4}, + {GUID_PKPixelFormat32bppRGBE, OutputKind::RGBE, 4}, +}; + +const DecodeTarget* find_decode_target(const PKPixelFormatGUID& guid) { + for (const DecodeTarget& candidate : kTargets) { + if (IsEqualGUID(candidate.guid, guid)) { + return &candidate; + } + } + + return nullptr; +} + +bool is_hdr_linear_target(OutputKind kind) { + switch (kind) { + case OutputKind::RGBAFloat: + case OutputKind::PRGBAFloat: + case OutputKind::RGBFloat: + case OutputKind::RGBFloatX: + case OutputKind::GRAYFloat: + case OutputKind::RGBAHalf: + case OutputKind::RGBHalf: + case OutputKind::RGBHalfX: + case OutputKind::GRAYHalf: + case OutputKind::RGBAFixed16: + case OutputKind::RGBFixed16: + case OutputKind::RGBFixed16X: + case OutputKind::GRAYFixed16: + case OutputKind::RGBAFixed32: + case OutputKind::RGBFixed32: + case OutputKind::RGBFixed32X: + case OutputKind::GRAYFixed32: + return true; + default: + return false; + } +} + +bool is_alpha_target(OutputKind kind) { + switch (kind) { + case OutputKind::RGBA8: + case OutputKind::PRGBA8: + case OutputKind::BGRA8: + case OutputKind::PBGRA8: + case OutputKind::RGBA16: + case OutputKind::PRGBA16: + case OutputKind::RGBAFloat: + case OutputKind::PRGBAFloat: + case OutputKind::RGBAHalf: + case OutputKind::RGBAFixed16: + case OutputKind::RGBAFixed32: + return true; + default: + return false; + } +} + +uint8_t unpremultiply_channel(uint8_t value, uint8_t alpha) { + if (alpha == 0) { + return 0; + } + + const int scaled = (static_cast(value) * 255 + alpha / 2) / alpha; + return static_cast(std::min(scaled, 255)); +} + +uint16_t unpremultiply_channel_16(uint16_t value, uint16_t alpha) { + if (alpha == 0) { + return 0; + } + + const uint32_t scaled = + (static_cast(value) * 65535u + alpha / 2u) / alpha; + return static_cast(std::min(scaled, 65535u)); +} + +float unpremultiply_channel_float(float value, float alpha) { + if (alpha <= 0.0f) { + return 0.0f; + } + + return value / alpha; +} + +template +T read_value(const uint8_t* ptr) { + T value; + std::memcpy(&value, ptr, sizeof(T)); + return value; +} + +float bitcast_float(uint32_t bits) { + float value; + std::memcpy(&value, &bits, sizeof(value)); + return value; +} + +float convert_half_to_float(uint16_t value) { + const uint32_t sign = (value >> 15) & 0x0001; + const uint32_t exponent = (value >> 10) & 0x001f; + const uint32_t mantissa = value & 0x03ff; + + if (exponent == 0) { + return bitcast_float(sign << 31); + } + + if (exponent == 0x1f) { + return bitcast_float((sign << 31) | (0xffu << 23) | (mantissa << 13)); + } + + return bitcast_float( + (sign << 31) | ((exponent - 15 + 127) << 23) | (mantissa << 13)); +} + +uint8_t convert_float_to_u8(float value) { + if (value <= 0.0f) { + return 0; + } + + if (value <= 0.0031308f) { + return static_cast((255.0f * value * 12.92f) + 0.5f); + } + + if (value < 1.0f) { + return static_cast( + (255.0f * ((1.055f * std::pow(value, 1.0f / 2.4f)) - 0.055f)) + + 0.5f); + } + + return 255; +} + +uint8_t convert_alpha_float_to_u8(float value) { + if (value <= 0.0f) { + return 0; + } + + if (value < 1.0f) { + return static_cast((255.0f * value) + 0.5f); + } + + return 255; +} + +float fixed16_to_float(int16_t value) { + return static_cast(value) * (1.0f / static_cast(1 << 13)); +} + +float fixed32_to_float(int32_t value) { + return static_cast(value) * (1.0f / static_cast(1 << 24)); +} + +float luma_rgb(float r, float g, float b) { + return r * 0.2126f + g * 0.7152f + b * 0.0722f; +} + +void scale_rgb(float& r, float& g, float& b, float luma_out) { + const float luma_in = luma_rgb(r, g, b); + if (luma_in <= 0.0f) { + r = 0.0f; + g = 0.0f; + b = 0.0f; + return; + } + + const float scale = luma_out / luma_in; + r *= scale; + g *= scale; + b *= scale; +} + +void tone_map_reinhard_luma( + float& r, + float& g, + float& b, + const ToneMapSettings& settings) { + r = std::max(r, 0.0f); + g = std::max(g, 0.0f); + b = std::max(b, 0.0f); + + if (!settings.enabled) { + return; + } + + const float white = std::max(settings.white, 1.0f); + const float white2 = white * white; + const float luma_in = luma_rgb(r, g, b); + const float luma_out = + luma_in * (1.0f + luma_in / white2) / (1.0f + luma_in); + scale_rgb(r, g, b, luma_out); +} + +void read_linear_rgb( + const uint8_t* pixel, + const DecodeTarget& target, + float& r, + float& g, + float& b) { + switch (target.kind) { + case OutputKind::RGBAFloat: + r = read_value(pixel + 0); + g = read_value(pixel + 4); + b = read_value(pixel + 8); + return; + case OutputKind::PRGBAFloat: { + const float alpha = read_value(pixel + 12); + r = unpremultiply_channel_float(read_value(pixel + 0), alpha); + g = unpremultiply_channel_float(read_value(pixel + 4), alpha); + b = unpremultiply_channel_float(read_value(pixel + 8), alpha); + return; + } + case OutputKind::RGBFloat: + case OutputKind::RGBFloatX: + r = read_value(pixel + 0); + g = read_value(pixel + 4); + b = read_value(pixel + 8); + return; + case OutputKind::GRAYFloat: + r = g = b = read_value(pixel); + return; + case OutputKind::RGBAHalf: + r = convert_half_to_float(read_value(pixel + 0)); + g = convert_half_to_float(read_value(pixel + 2)); + b = convert_half_to_float(read_value(pixel + 4)); + return; + case OutputKind::RGBHalf: + case OutputKind::RGBHalfX: + r = convert_half_to_float(read_value(pixel + 0)); + g = convert_half_to_float(read_value(pixel + 2)); + b = convert_half_to_float(read_value(pixel + 4)); + return; + case OutputKind::GRAYHalf: + r = g = b = convert_half_to_float(read_value(pixel)); + return; + case OutputKind::RGBAFixed16: + r = fixed16_to_float(read_value(pixel + 0)); + g = fixed16_to_float(read_value(pixel + 2)); + b = fixed16_to_float(read_value(pixel + 4)); + return; + case OutputKind::RGBFixed16: + case OutputKind::RGBFixed16X: + r = fixed16_to_float(read_value(pixel + 0)); + g = fixed16_to_float(read_value(pixel + 2)); + b = fixed16_to_float(read_value(pixel + 4)); + return; + case OutputKind::GRAYFixed16: + r = g = b = fixed16_to_float(read_value(pixel)); + return; + case OutputKind::RGBAFixed32: + r = fixed32_to_float(read_value(pixel + 0)); + g = fixed32_to_float(read_value(pixel + 4)); + b = fixed32_to_float(read_value(pixel + 8)); + return; + case OutputKind::RGBFixed32: + case OutputKind::RGBFixed32X: + r = fixed32_to_float(read_value(pixel + 0)); + g = fixed32_to_float(read_value(pixel + 4)); + b = fixed32_to_float(read_value(pixel + 8)); + return; + case OutputKind::GRAYFixed32: + r = g = b = fixed32_to_float(read_value(pixel)); + return; + default: + r = 0.0f; + g = 0.0f; + b = 0.0f; + return; + } +} + +float read_alpha_sample(const uint8_t* pixel, const DecodeTarget& target) { + switch (target.kind) { + case OutputKind::RGBA8: + case OutputKind::PRGBA8: + case OutputKind::BGRA8: + case OutputKind::PBGRA8: + return static_cast(pixel[3]) * (1.0f / 255.0f); + case OutputKind::RGBA16: + case OutputKind::PRGBA16: + return static_cast(read_value(pixel + 6)) * + (1.0f / 65535.0f); + case OutputKind::RGBAFloat: + case OutputKind::PRGBAFloat: + return read_value(pixel + 12); + case OutputKind::RGBAHalf: + return convert_half_to_float(read_value(pixel + 6)); + case OutputKind::RGBAFixed16: + return fixed16_to_float(read_value(pixel + 6)); + case OutputKind::RGBAFixed32: + return fixed32_to_float(read_value(pixel + 12)); + default: + return 1.0f; + } +} + +bool should_preserve_alpha( + const uint8_t* decoded_pixels, + size_t pixel_count, + const DecodeTarget& target, + bool has_alpha) { + if (!has_alpha || !is_alpha_target(target.kind)) { + return false; + } + + if (!is_hdr_linear_target(target.kind) || pixel_count == 0) { + return true; + } + + const size_t sample_stride = + std::max(1, pixel_count / kToneMapSampleCount); + for (size_t i = 0; i < pixel_count; i += sample_stride) { + const float alpha = read_alpha_sample( + decoded_pixels + (i * target.bytes_per_pixel), target); + if (std::isfinite(alpha) && alpha > 0.000001f) { + return true; + } + } + + return false; +} + +void assign_rgba( + std::vector& rgba_pixels, + size_t offset, + uint8_t r, + uint8_t g, + uint8_t b, + uint8_t a) { + rgba_pixels[offset + 0] = r; + rgba_pixels[offset + 1] = g; + rgba_pixels[offset + 2] = b; + rgba_pixels[offset + 3] = a; +} + +void assign_rgba( + uint8_t* rgba_pixels, + size_t offset, + uint8_t r, + uint8_t g, + uint8_t b, + uint8_t a) { + rgba_pixels[offset + 0] = r; + rgba_pixels[offset + 1] = g; + rgba_pixels[offset + 2] = b; + rgba_pixels[offset + 3] = a; +} + +void assign_linear_rgba( + uint8_t* rgba_pixels, + size_t offset, + float r, + float g, + float b, + float a, + bool has_alpha, + const ToneMapSettings& tone_map) { + tone_map_reinhard_luma(r, g, b, tone_map); + if (!has_alpha) { + a = 1.0f; + } + assign_rgba( + rgba_pixels, offset, + convert_float_to_u8(r), + convert_float_to_u8(g), + convert_float_to_u8(b), + convert_alpha_float_to_u8(a)); +} + +val create_image_data(const std::vector& rgba, int width, int height) { + return ImageData.new_( + Uint8ClampedArray.new_(typed_memory_view(rgba.size(), rgba.data())), + width, height); +} + +ToneMapSettings compute_tone_map_settings( + const uint8_t* decoded_pixels, + size_t pixel_count, + const DecodeTarget& target) { + if (!is_hdr_linear_target(target.kind) || pixel_count == 0) { + return {false, 1.0f}; + } + + const size_t sample_stride = + std::max(1, pixel_count / kToneMapSampleCount); + std::vector luminance_samples; + luminance_samples.reserve((pixel_count + sample_stride - 1) / sample_stride); + + float max_channel = 0.0f; + for (size_t i = 0; i < pixel_count; i += sample_stride) { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + read_linear_rgb( + decoded_pixels + (i * target.bytes_per_pixel), target, r, g, b); + r = std::max(r, 0.0f); + g = std::max(g, 0.0f); + b = std::max(b, 0.0f); + max_channel = std::max(max_channel, std::max(r, std::max(g, b))); + luminance_samples.push_back(luma_rgb(r, g, b)); + } + + if (luminance_samples.empty()) { + return {false, 1.0f}; + } + + std::sort(luminance_samples.begin(), luminance_samples.end()); + const size_t white_index = static_cast( + (luminance_samples.size() - 1) * kToneMapWhitePercentile); + const float white = luminance_samples[white_index]; + + if ((!std::isfinite(white) || white <= 1.0f) && max_channel <= 1.0f) { + return {false, 1.0f}; + } + + return {true, std::max(white, 1.0f)}; +} + +void convert_decoded_pixels_to_rgba( + const uint8_t* decoded_pixels, + size_t pixel_count, + const DecodeTarget& target, + bool has_alpha, + uint8_t* rgba_pixels) { + const ToneMapSettings tone_map = + compute_tone_map_settings(decoded_pixels, pixel_count, target); + const bool use_alpha = + should_preserve_alpha(decoded_pixels, pixel_count, target, has_alpha); + + for (size_t i = 0; i < pixel_count; ++i) { + const uint8_t* pixel = decoded_pixels + (i * target.bytes_per_pixel); + const size_t dst = i * 4; + + switch (target.kind) { + case OutputKind::RGBA8: + rgba_pixels[dst + 0] = pixel[0]; + rgba_pixels[dst + 1] = pixel[1]; + rgba_pixels[dst + 2] = pixel[2]; + rgba_pixels[dst + 3] = use_alpha ? pixel[3] : 255; + break; + case OutputKind::PRGBA8: { + const uint8_t alpha = use_alpha ? pixel[3] : 255; + assign_rgba( + rgba_pixels, dst, + unpremultiply_channel(pixel[0], alpha), + unpremultiply_channel(pixel[1], alpha), + unpremultiply_channel(pixel[2], alpha), + alpha); + break; + } + case OutputKind::BGRA8: + assign_rgba( + rgba_pixels, dst, pixel[2], pixel[1], pixel[0], use_alpha ? pixel[3] : 255); + break; + case OutputKind::PBGRA8: { + const uint8_t alpha = use_alpha ? pixel[3] : 255; + assign_rgba( + rgba_pixels, dst, + unpremultiply_channel(pixel[2], alpha), + unpremultiply_channel(pixel[1], alpha), + unpremultiply_channel(pixel[0], alpha), + alpha); + break; + } + case OutputKind::RGB8: + assign_rgba(rgba_pixels, dst, pixel[0], pixel[1], pixel[2], 255); + break; + case OutputKind::BGR8: + assign_rgba(rgba_pixels, dst, pixel[2], pixel[1], pixel[0], 255); + break; + case OutputKind::RGBX8: + assign_rgba(rgba_pixels, dst, pixel[0], pixel[1], pixel[2], 255); + break; + case OutputKind::BGRX8: + assign_rgba(rgba_pixels, dst, pixel[2], pixel[1], pixel[0], 255); + break; + case OutputKind::GRAY8: + assign_rgba(rgba_pixels, dst, pixel[0], pixel[0], pixel[0], 255); + break; + case OutputKind::RGBA16: + assign_rgba( + rgba_pixels, dst, + read_value(pixel + 0) >> 8, + read_value(pixel + 2) >> 8, + read_value(pixel + 4) >> 8, + use_alpha ? (read_value(pixel + 6) >> 8) : 255); + break; + case OutputKind::PRGBA16: { + const uint16_t alpha = use_alpha ? read_value(pixel + 6) : 65535u; + assign_rgba( + rgba_pixels, dst, + unpremultiply_channel_16(read_value(pixel + 0), alpha) >> 8, + unpremultiply_channel_16(read_value(pixel + 2), alpha) >> 8, + unpremultiply_channel_16(read_value(pixel + 4), alpha) >> 8, + alpha >> 8); + break; + } + case OutputKind::RGB16: + assign_rgba( + rgba_pixels, dst, + read_value(pixel + 0) >> 8, + read_value(pixel + 2) >> 8, + read_value(pixel + 4) >> 8, + 255); + break; + case OutputKind::RGB16X: + assign_rgba( + rgba_pixels, dst, + read_value(pixel + 0) >> 8, + read_value(pixel + 2) >> 8, + read_value(pixel + 4) >> 8, + 255); + break; + case OutputKind::GRAY16: { + const uint8_t gray = read_value(pixel) >> 8; + assign_rgba(rgba_pixels, dst, gray, gray, gray, 255); + break; + } + case OutputKind::RGBAFloat: { + assign_linear_rgba( + rgba_pixels, + dst, + read_value(pixel + 0), + read_value(pixel + 4), + read_value(pixel + 8), + read_value(pixel + 12), + use_alpha, + tone_map); + break; + } + case OutputKind::PRGBAFloat: { + const float alpha = use_alpha ? read_value(pixel + 12) : 1.0f; + assign_linear_rgba( + rgba_pixels, + dst, + unpremultiply_channel_float(read_value(pixel + 0), alpha), + unpremultiply_channel_float(read_value(pixel + 4), alpha), + unpremultiply_channel_float(read_value(pixel + 8), alpha), + alpha, + use_alpha, + tone_map); + break; + } + case OutputKind::RGBFloat: + assign_linear_rgba( + rgba_pixels, + dst, + read_value(pixel + 0), + read_value(pixel + 4), + read_value(pixel + 8), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::RGBFloatX: + assign_linear_rgba( + rgba_pixels, + dst, + read_value(pixel + 0), + read_value(pixel + 4), + read_value(pixel + 8), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::GRAYFloat: { + const float gray = read_value(pixel); + assign_linear_rgba( + rgba_pixels, dst, gray, gray, gray, 1.0f, use_alpha, tone_map); + break; + } + case OutputKind::RGBAHalf: + assign_linear_rgba( + rgba_pixels, + dst, + convert_half_to_float(read_value(pixel + 0)), + convert_half_to_float(read_value(pixel + 2)), + convert_half_to_float(read_value(pixel + 4)), + convert_half_to_float(read_value(pixel + 6)), + use_alpha, + tone_map); + break; + case OutputKind::RGBHalf: + assign_linear_rgba( + rgba_pixels, + dst, + convert_half_to_float(read_value(pixel + 0)), + convert_half_to_float(read_value(pixel + 2)), + convert_half_to_float(read_value(pixel + 4)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::RGBHalfX: + assign_linear_rgba( + rgba_pixels, + dst, + convert_half_to_float(read_value(pixel + 0)), + convert_half_to_float(read_value(pixel + 2)), + convert_half_to_float(read_value(pixel + 4)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::GRAYHalf: { + const float gray = + convert_half_to_float(read_value(pixel)); + assign_linear_rgba( + rgba_pixels, dst, gray, gray, gray, 1.0f, use_alpha, tone_map); + break; + } + case OutputKind::RGBAFixed16: + assign_linear_rgba( + rgba_pixels, + dst, + fixed16_to_float(read_value(pixel + 0)), + fixed16_to_float(read_value(pixel + 2)), + fixed16_to_float(read_value(pixel + 4)), + fixed16_to_float(read_value(pixel + 6)), + use_alpha, + tone_map); + break; + case OutputKind::RGBFixed16: + assign_linear_rgba( + rgba_pixels, + dst, + fixed16_to_float(read_value(pixel + 0)), + fixed16_to_float(read_value(pixel + 2)), + fixed16_to_float(read_value(pixel + 4)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::RGBFixed16X: + assign_linear_rgba( + rgba_pixels, + dst, + fixed16_to_float(read_value(pixel + 0)), + fixed16_to_float(read_value(pixel + 2)), + fixed16_to_float(read_value(pixel + 4)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::GRAYFixed16: { + const float gray = + fixed16_to_float(read_value(pixel)); + assign_linear_rgba( + rgba_pixels, dst, gray, gray, gray, 1.0f, use_alpha, tone_map); + break; + } + case OutputKind::RGBAFixed32: + assign_linear_rgba( + rgba_pixels, + dst, + fixed32_to_float(read_value(pixel + 0)), + fixed32_to_float(read_value(pixel + 4)), + fixed32_to_float(read_value(pixel + 8)), + fixed32_to_float(read_value(pixel + 12)), + use_alpha, + tone_map); + break; + case OutputKind::RGBFixed32: + assign_linear_rgba( + rgba_pixels, + dst, + fixed32_to_float(read_value(pixel + 0)), + fixed32_to_float(read_value(pixel + 4)), + fixed32_to_float(read_value(pixel + 8)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::RGBFixed32X: + assign_linear_rgba( + rgba_pixels, + dst, + fixed32_to_float(read_value(pixel + 0)), + fixed32_to_float(read_value(pixel + 4)), + fixed32_to_float(read_value(pixel + 8)), + 1.0f, + use_alpha, + tone_map); + break; + case OutputKind::GRAYFixed32: { + const float gray = + fixed32_to_float(read_value(pixel)); + assign_linear_rgba( + rgba_pixels, dst, gray, gray, gray, 1.0f, use_alpha, tone_map); + break; + } + case OutputKind::RGB101010: { + const uint32_t value = read_value(pixel); + assign_rgba( + rgba_pixels, dst, + static_cast(((value >> 20) & 0x3ff) >> 2), + static_cast(((value >> 10) & 0x3ff) >> 2), + static_cast((value & 0x3ff) >> 2), + 255); + break; + } + case OutputKind::RGBE: { + const uint8_t exponent = pixel[3]; + if (exponent == 0) { + assign_rgba(rgba_pixels, dst, 0, 0, 0, 255); + break; + } + + const int adjusted_exponent = static_cast(exponent) - 128 - 8; + const float scale = std::ldexp(1.0f, adjusted_exponent); + assign_rgba( + rgba_pixels, dst, + convert_float_to_u8(static_cast(pixel[0]) * scale), + convert_float_to_u8(static_cast(pixel[1]) * scale), + convert_float_to_u8(static_cast(pixel[2]) * scale), + 255); + break; + } + } + } +} + +template +bool decode_pixels_to_rgba( + int width, + int height, + const DecodeTarget& target, + CopyFn copy_pixels, + bool has_alpha, + std::vector& rgba_pixels) { + const size_t pixel_count = + static_cast(width) * static_cast(height); + const size_t row_bytes = + static_cast(width) * static_cast(target.bytes_per_pixel); + std::vector decoded_pixels(pixel_count * target.bytes_per_pixel); + PKRect rect = {0, 0, width, height}; + + if (!copy_pixels(&rect, decoded_pixels.data(), row_bytes)) { + return false; + } + + rgba_pixels.resize(pixel_count * 4); + convert_decoded_pixels_to_rgba( + decoded_pixels.data(), pixel_count, target, has_alpha, rgba_pixels.data()); + return true; +} +} // namespace + +val decode(std::string jxrimage) { + struct WMPStream* stream = nullptr; + if (CreateWS_Memory(&stream, (void*)jxrimage.data(), jxrimage.size())) { + return val::null(); + } + + PKImageDecode* decoder = nullptr; + if (PKImageDecode_Create_WMP(&decoder) || !decoder) { + if (stream) { + stream->Close(&stream); + } + return val::null(); + } + + if (decoder->Initialize(decoder, stream)) { + decoder->Release(&decoder); + return val::null(); + } + + int width = 0; + int height = 0; + if (decoder->GetSize(decoder, &width, &height) || width <= 0 || height <= 0) { + decoder->Release(&decoder); + return val::null(); + } + + const bool has_alpha = + decoder->WMP.bHasAlpha || decoder->WMP.wmiSCP.uAlphaMode > 0; + + PKPixelFormatGUID source_guid; + std::vector rgba_pixels; + + if (!decoder->GetPixelFormat(decoder, &source_guid)) { + const DecodeTarget* source_target = find_decode_target(source_guid); + if (source_target && + decode_pixels_to_rgba( + width, + height, + *source_target, + [&](const PKRect* rect, uint8_t* pixels, size_t row_bytes) { + return !decoder->Copy( + decoder, + rect, + pixels, + static_cast(row_bytes)); + }, + has_alpha, + rgba_pixels)) { + decoder->Release(&decoder); + return create_image_data(rgba_pixels, width, height); + } + } + + for (const DecodeTarget& candidate : kTargets) { + PKFormatConverter* converter = nullptr; + if (PKCodecFactory_CreateFormatConverter(&converter) || !converter) { + decoder->Release(&decoder); + return val::null(); + } + + if (converter->Initialize(converter, decoder, nullptr, candidate.guid)) { + converter->Release(&converter); + continue; + } + + const bool decoded = decode_pixels_to_rgba( + width, + height, + candidate, + [&](const PKRect* rect, uint8_t* pixels, size_t row_bytes) { + return !converter->Copy( + converter, + rect, + pixels, + static_cast(row_bytes)); + }, + has_alpha, + rgba_pixels); + converter->Release(&converter); + + if (decoded) { + decoder->Release(&decoder); + return create_image_data(rgba_pixels, width, height); + } + } + + decoder->Release(&decoder); + return val::null(); +} + +EMSCRIPTEN_BINDINGS(my_module) { + function("decode", &decode); +} diff --git a/packages/jxr/dist/codec/dec/jxr_dec.d.ts b/packages/jxr/dist/codec/dec/jxr_dec.d.ts new file mode 100644 index 0000000..c6262ab --- /dev/null +++ b/packages/jxr/dist/codec/dec/jxr_dec.d.ts @@ -0,0 +1,7 @@ +export interface JXRModule extends EmscriptenWasm.Module { + decode(data: BufferSource): ImageData | null; +} + +declare var moduleFactory: EmscriptenWasm.ModuleFactory; + +export default moduleFactory; diff --git a/packages/jxr/dist/codec/dec/jxr_dec.js b/packages/jxr/dist/codec/dec/jxr_dec.js new file mode 100644 index 0000000..be6abe5 --- /dev/null +++ b/packages/jxr/dist/codec/dec/jxr_dec.js @@ -0,0 +1,2940 @@ + +var Module = (() => { + var _scriptDir = import.meta.url; + + return ( +function(moduleArg = {}) { + +// include: shell.js +// The Module object: Our interface to the outside world. We import +// and export values on it. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to check if Module already exists (e.g. case 3 above). +// Substitution will be replaced with actual code on later stage of the build, +// this way Closure Compiler will not mangle it (e.g. case 4. above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module = moduleArg; + +// Set up the promise that indicates the Module is initialized +var readyPromiseResolve, readyPromiseReject; +var readyPromise = new Promise((resolve, reject) => { + readyPromiseResolve = resolve; + readyPromiseReject = reject; +}); +["_memory","___indirect_function_table","onRuntimeInitialized"].forEach((prop) => { + if (!Object.getOwnPropertyDescriptor(readyPromise, prop)) { + Object.defineProperty(readyPromise, prop, { + get: () => abort('You are getting ' + prop + ' on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js'), + set: () => abort('You are setting ' + prop + ' on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js'), + }); + } +}); + +// --pre-jses are emitted after the Module integration code, so that they can +// refer to Module (if they choose; they can also define Module) +// include: /src/pre.js +const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; +const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; +const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; + +if (isRunningInCloudFlareWorkers || isRunningInNode) { + if (!globalThis.ImageData) { + // Simple Polyfill for ImageData Object + globalThis.ImageData = class ImageData { + constructor(data, width, height) { + this.data = data; + this.width = width; + this.height = height; + } + }; + } + + if (import.meta.url === undefined) { + import.meta.url = 'https://localhost'; + } + + if (typeof self !== 'undefined' && self.location === undefined) { + self.location = { href: '' }; + } +} +// end include: /src/pre.js + + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = Object.assign({}, Module); + +var arguments_ = []; +var thisProgram = './this.program'; +var quit_ = (status, toThrow) => { + throw toThrow; +}; + +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). + +// Attempt to auto-detect the environment +var ENVIRONMENT_IS_WEB = typeof window == 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function'; +// N.b. Electron.js environment is simultaneously a NODE-environment, but +// also a web environment. +var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (Module['ENVIRONMENT']) { + throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); +} + +// `/` should be present at the end if `scriptDirectory` is not empty +var scriptDirectory = ''; +function locateFile(path) { + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; +} + +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary; + +if (ENVIRONMENT_IS_SHELL) { + + if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + +} else + +// Note that this includes Node.js workers when relevant (pthreads is enabled). +// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and +// ENVIRONMENT_IS_NODE. +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled + scriptDirectory = self.location.href; + } else if (typeof document != 'undefined' && document.currentScript) { // web + scriptDirectory = document.currentScript.src; + } + // When MODULARIZE, this JS may be executed later, after document.currentScript + // is gone, so we saved it, and we use it here instead of any other info. + if (_scriptDir) { + scriptDirectory = _scriptDir; + } + // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. + // otherwise, slice off the final part of the url to find the script directory. + // if scriptDirectory does not contain a slash, lastIndexOf will return -1, + // and scriptDirectory will correctly be replaced with an empty string. + // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #), + // they are removed because they could contain a slash. + if (scriptDirectory.startsWith('blob:')) { + scriptDirectory = ''; + } else { + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, '').lastIndexOf('/')+1); + } + + if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + // Differentiate the Web Worker from the Node Worker case, as reading must + // be done differently. + { +// include: web_or_worker_shell_read.js +read_ = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + } + + if (ENVIRONMENT_IS_WORKER) { + readBinary = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.responseType = 'arraybuffer'; + xhr.send(null); + return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); + }; + } + + readAsync = (url, onload, onerror) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = () => { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + return; + } + onerror(); + }; + xhr.onerror = onerror; + xhr.send(null); + } + +// end include: web_or_worker_shell_read.js + } +} else +{ + throw new Error('environment detection error'); +} + +var out = Module['print'] || console.log.bind(console); +var err = Module['printErr'] || console.error.bind(console); + +// Merge back in the overrides +Object.assign(Module, moduleOverrides); +// Free the object hierarchy contained in the overrides, this lets the GC +// reclaim data used. +moduleOverrides = null; +checkIncomingModuleAPI(); + +// Emit code to handle expected values on the Module object. This applies Module.x +// to the proper local x. This has two benefits: first, we only emit it if it is +// expected to arrive, and second, by using a local everywhere else that can be +// minified. + +if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_'); + +if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram'); + +if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_'); + +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message +// Assertions on removed incoming Module JS APIs. +assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)'); +assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)'); +assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); +assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)'); +assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); +legacyModuleProp('asm', 'wasmExports'); +legacyModuleProp('read', 'read_'); +legacyModuleProp('readAsync', 'readAsync'); +legacyModuleProp('readBinary', 'readBinary'); +legacyModuleProp('setWindowTitle', 'setWindowTitle'); +var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js'; +var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js'; +var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js'; +var FETCHFS = 'FETCHFS is no longer included by default; build with -lfetchfs.js'; +var ICASEFS = 'ICASEFS is no longer included by default; build with -licasefs.js'; +var JSFILEFS = 'JSFILEFS is no longer included by default; build with -ljsfilefs.js'; +var OPFS = 'OPFS is no longer included by default; build with -lopfs.js'; + +var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; + +assert(!ENVIRONMENT_IS_NODE, 'node environment detected but not enabled at build time. Add `node` to `-sENVIRONMENT` to enable.'); + +assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.'); + +// end include: shell.js + +// include: preamble.js +// === Preamble library stuff === + +// Documentation for the public APIs defined in this file must be updated in: +// site/source/docs/api_reference/preamble.js.rst +// A prebuilt local version of the documentation is available at: +// site/build/text/docs/api_reference/preamble.js.txt +// You can also build docs locally as HTML or other formats in site/ +// An online HTML version (which may be of a different version of Emscripten) +// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html + +var wasmBinary; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); + +if (typeof WebAssembly != 'object') { + err('no native wasm support detected'); +} + +// Wasm globals + +var wasmMemory; + +//======================================== +// Runtime essentials +//======================================== + +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. +var EXITSTATUS; + +// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we +// don't define it at all in release modes. This matches the behaviour of +// MINIMAL_RUNTIME. +// TODO(sbc): Make this the default even without STRICT enabled. +/** @type {function(*, string=)} */ +function assert(condition, text) { + if (!condition) { + abort('Assertion failed' + (text ? ': ' + text : '')); + } +} + +// We used to include malloc/free by default in the past. Show a helpful error in +// builds with assertions. + +// Memory management + +var HEAP, +/** @type {!Int8Array} */ + HEAP8, +/** @type {!Uint8Array} */ + HEAPU8, +/** @type {!Int16Array} */ + HEAP16, +/** @type {!Uint16Array} */ + HEAPU16, +/** @type {!Int32Array} */ + HEAP32, +/** @type {!Uint32Array} */ + HEAPU32, +/** @type {!Float32Array} */ + HEAPF32, +/** @type {!Float64Array} */ + HEAPF64; + +// include: runtime_shared.js +function updateMemoryViews() { + var b = wasmMemory.buffer; + Module['HEAP8'] = HEAP8 = new Int8Array(b); + Module['HEAP16'] = HEAP16 = new Int16Array(b); + Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); + Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); + Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); + Module['HEAPF32'] = HEAPF32 = new Float32Array(b); + Module['HEAPF64'] = HEAPF64 = new Float64Array(b); +} +// end include: runtime_shared.js +assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') + +assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined, + 'JS engine does not provide full typed array support'); + +// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY +assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally'); +assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically'); + +// include: runtime_stack_check.js +// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. +function writeStackCookie() { + var max = _emscripten_stack_get_end(); + assert((max & 3) == 0); + // If the stack ends at address zero we write our cookies 4 bytes into the + // stack. This prevents interference with SAFE_HEAP and ASAN which also + // monitor writes to address zero. + if (max == 0) { + max += 4; + } + // The stack grow downwards towards _emscripten_stack_get_end. + // We write cookies to the final two words in the stack and detect if they are + // ever overwritten. + HEAPU32[((max)>>2)] = 0x02135467; + HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE; + // Also test the global address 0 for integrity. + HEAPU32[((0)>>2)] = 1668509029; +} + +function checkStackCookie() { + if (ABORT) return; + var max = _emscripten_stack_get_end(); + // See writeStackCookie(). + if (max == 0) { + max += 4; + } + var cookie1 = HEAPU32[((max)>>2)]; + var cookie2 = HEAPU32[(((max)+(4))>>2)]; + if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) { + abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`); + } + // Also test the global address 0 for integrity. + if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) { + abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); + } +} +// end include: runtime_stack_check.js +// include: runtime_assertions.js +// Endianness check +(function() { + var h16 = new Int16Array(1); + var h8 = new Int8Array(h16.buffer); + h16[0] = 0x6373; + if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'; +})(); + +// end include: runtime_assertions.js +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the main() is called + +var runtimeInitialized = false; + +function preRun() { + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function initRuntime() { + assert(!runtimeInitialized); + runtimeInitialized = true; + + checkStackCookie(); + + + callRuntimeCallbacks(__ATINIT__); +} + +function postRun() { + checkStackCookie(); + + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} + +function addOnExit(cb) { +} + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} + +// include: runtime_math.js +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc + +assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +// end include: runtime_math.js +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// Module.preRun (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled +var runDependencyTracking = {}; + +function getUniqueRunDependency(id) { + var orig = id; + while (1) { + if (!runDependencyTracking[id]) return id; + id = orig + Math.random(); + } +} + +function addRunDependency(id) { + runDependencies++; + + Module['monitorRunDependencies']?.(runDependencies); + + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + if (runDependencyWatcher === null && typeof setInterval != 'undefined') { + // Check for missing dependencies every few seconds + runDependencyWatcher = setInterval(() => { + if (ABORT) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + return; + } + var shown = false; + for (var dep in runDependencyTracking) { + if (!shown) { + shown = true; + err('still waiting on run dependencies:'); + } + err(`dependency: ${dep}`); + } + if (shown) { + err('(end of list)'); + } + }, 10000); + } + } else { + err('warning: run dependency added without ID'); + } +} + +function removeRunDependency(id) { + runDependencies--; + + Module['monitorRunDependencies']?.(runDependencies); + + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } else { + err('warning: run dependency removed without ID'); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} + +/** @param {string|number=} what */ +function abort(what) { + Module['onAbort']?.(what); + + what = 'Aborted(' + what + ')'; + // TODO(sbc): Should we remove printing and leave it up to whoever + // catches the exception? + err(what); + + ABORT = true; + EXITSTATUS = 1; + + // Use a wasm runtime error, because a JS error might be seen as a foreign + // exception, which means we'd run destructors on it. We need the error to + // simply make the program stop. + // FIXME This approach does not work in Wasm EH because it currently does not assume + // all RuntimeErrors are from traps; it decides whether a RuntimeError is from + // a trap or not based on a hidden field within the object. So at the moment + // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that + // allows this in the wasm spec. + + // Suppress closure compiler warning here. Closure compiler's builtin extern + // definition for WebAssembly.RuntimeError claims it takes no arguments even + // though it can. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. + /** @suppress {checkTypes} */ + var e = new WebAssembly.RuntimeError(what); + + readyPromiseReject(e); + // Throw the error whether or not MODULARIZE is set because abort is used + // in code paths apart from instantiation where an exception is expected + // to be thrown when abort is called. + throw e; +} + +// include: memoryprofiler.js +// end include: memoryprofiler.js +// show errors on likely calls to FS when it was not included +var FS = { + error() { + abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -sFORCE_FILESYSTEM'); + }, + init() { FS.error() }, + createDataFile() { FS.error() }, + createPreloadedFile() { FS.error() }, + createLazyFile() { FS.error() }, + open() { FS.error() }, + mkdev() { FS.error() }, + registerDevice() { FS.error() }, + analyzePath() { FS.error() }, + + ErrnoError() { FS.error() }, +}; +Module['FS_createDataFile'] = FS.createDataFile; +Module['FS_createPreloadedFile'] = FS.createPreloadedFile; + +// include: URIUtils.js +// Prefix of data URIs emitted by SINGLE_FILE and related options. +var dataURIPrefix = 'data:application/octet-stream;base64,'; + +/** + * Indicates whether filename is a base64 data URI. + * @noinline + */ +var isDataURI = (filename) => filename.startsWith(dataURIPrefix); + +/** + * Indicates whether filename is delivered via file protocol (as opposed to http/https) + * @noinline + */ +var isFileURI = (filename) => filename.startsWith('file://'); +// end include: URIUtils.js +function createExportWrapper(name, nargs) { + return (...args) => { + assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`); + var f = wasmExports[name]; + assert(f, `exported native function \`${name}\` not found`); + // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled. + assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`); + return f(...args); + }; +} + +// include: runtime_exceptions.js +// end include: runtime_exceptions.js +var wasmBinaryFile; +if (Module['locateFile']) { + wasmBinaryFile = 'jxr_dec.wasm'; + if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); + } +} else { + // Use bundler-friendly `new URL(..., import.meta.url)` pattern; works in browsers too. + wasmBinaryFile = new URL('jxr_dec.wasm', import.meta.url).href; +} + +function getBinarySync(file) { + if (file == wasmBinaryFile && wasmBinary) { + return new Uint8Array(wasmBinary); + } + if (readBinary) { + return readBinary(file); + } + throw 'both async and sync fetching of the wasm failed'; +} + +function getBinaryPromise(binaryFile) { + // If we don't have the binary yet, try to load it asynchronously. + // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. + // See https://github.com/github/fetch/pull/92#issuecomment-140665932 + // Cordova or Electron apps are typically loaded from a file:// url. + // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. + if (!wasmBinary + && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { + if (typeof fetch == 'function' + ) { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + throw `failed to load wasm binary file at '${binaryFile}'`; + } + return response['arrayBuffer'](); + }).catch(() => getBinarySync(binaryFile)); + } + } + + // Otherwise, getBinarySync should be able to get it synchronously + return Promise.resolve().then(() => getBinarySync(binaryFile)); +} + +function instantiateArrayBuffer(binaryFile, imports, receiver) { + return getBinaryPromise(binaryFile).then((binary) => { + return WebAssembly.instantiate(binary, imports); + }).then(receiver, (reason) => { + err(`failed to asynchronously prepare wasm: ${reason}`); + + // Warn on some common problems. + if (isFileURI(wasmBinaryFile)) { + err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`); + } + abort(reason); + }); +} + +function instantiateAsync(binary, binaryFile, imports, callback) { + if (!binary && + typeof WebAssembly.instantiateStreaming == 'function' && + !isDataURI(binaryFile) && + typeof fetch == 'function') { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + // Suppress closure warning here since the upstream definition for + // instantiateStreaming only allows Promise rather than + // an actual Response. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. + /** @suppress {checkTypes} */ + var result = WebAssembly.instantiateStreaming(response, imports); + + return result.then( + callback, + function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err(`wasm streaming compile failed: ${reason}`); + err('falling back to ArrayBuffer instantiation'); + return instantiateArrayBuffer(binaryFile, imports, callback); + }); + }); + } + return instantiateArrayBuffer(binaryFile, imports, callback); +} + +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +function createWasm() { + // prepare imports + var info = { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + }; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + /** @param {WebAssembly.Module=} module*/ + function receiveInstance(instance, module) { + wasmExports = instance.exports; + + + + wasmMemory = wasmExports['memory']; + + assert(wasmMemory, 'memory not found in wasm exports'); + updateMemoryViews(); + + wasmTable = wasmExports['__indirect_function_table']; + + assert(wasmTable, 'table not found in wasm exports'); + + addOnInit(wasmExports['__wasm_call_ctors']); + + removeRunDependency('wasm-instantiate'); + return wasmExports; + } + // wait for the pthread pool (if any) + addRunDependency('wasm-instantiate'); + + // Prefer streaming instantiation if available. + // Async compilation can be confusing when an error on the page overwrites Module + // (for example, if the order of elements is wrong, and the one defining Module is + // later), so we save Module and check it later. + var trueModule = Module; + function receiveInstantiationResult(result) { + // 'result' is a ResultObject object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); + trueModule = null; + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. + // When the regression is fixed, can restore the above PTHREADS-enabled path. + receiveInstance(result['instance']); + } + + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to + // run the instantiation parallel to any other async startup actions they are + // performing. + // Also pthreads and wasm workers initialize the wasm instance through this + // path. + if (Module['instantiateWasm']) { + + try { + return Module['instantiateWasm'](info, receiveInstance); + } catch(e) { + err(`Module.instantiateWasm callback failed with error: ${e}`); + // If instantiation fails, reject the module ready promise. + readyPromiseReject(e); + } + } + + // If instantiation fails, reject the module ready promise. + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject); + return {}; // no exports yet; we'll fill them in later +} + +// Globals used by JS i64 conversions (see makeSetValue) +var tempDouble; +var tempI64; + +// include: runtime_debug.js +function legacyModuleProp(prop, newName, incoming=true) { + if (!Object.getOwnPropertyDescriptor(Module, prop)) { + Object.defineProperty(Module, prop, { + configurable: true, + get() { + let extra = incoming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : ''; + abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra); + + } + }); + } +} + +function ignoredModuleProp(prop) { + if (Object.getOwnPropertyDescriptor(Module, prop)) { + abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`); + } +} + +// forcing the filesystem exports a few things by default +function isExportedByForceFilesystem(name) { + return name === 'FS_createPath' || + name === 'FS_createDataFile' || + name === 'FS_createPreloadedFile' || + name === 'FS_unlink' || + name === 'addRunDependency' || + // The old FS has some functionality that WasmFS lacks. + name === 'FS_createLazyFile' || + name === 'FS_createDevice' || + name === 'removeRunDependency'; +} + +function missingGlobal(sym, msg) { + if (typeof globalThis != 'undefined') { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`); + return undefined; + } + }); + } +} + +missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer'); +missingGlobal('asm', 'Please use wasmExports instead'); + +function missingLibrarySymbol(sym) { + if (typeof globalThis != 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + // Can't `abort()` here because it would break code that does runtime + // checks. e.g. `if (typeof SDL === 'undefined')`. + var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`; + // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in + // library.js, which means $name for a JS name with no prefix, or name + // for a JS name like _name. + var librarySymbol = sym; + if (!librarySymbol.startsWith('_')) { + librarySymbol = '$' + sym; + } + msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + warnOnce(msg); + return undefined; + } + }); + } + // Any symbol that is not included from the JS library is also (by definition) + // not exported on the Module object. + unexportedRuntimeSymbol(sym); +} + +function unexportedRuntimeSymbol(sym) { + if (!Object.getOwnPropertyDescriptor(Module, sym)) { + Object.defineProperty(Module, sym, { + configurable: true, + get() { + var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + abort(msg); + } + }); + } +} + +// Used by XXXXX_DEBUG settings to output debug messages. +function dbg(...args) { + // TODO(sbc): Make this configurable somehow. Its not always convenient for + // logging to show up as warnings. + console.warn(...args); +} +// end include: runtime_debug.js +// === Body === +// end include: preamble.js + + + /** @constructor */ + function ExitStatus(status) { + this.name = 'ExitStatus'; + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + // Pass the module as the first argument. + callbacks.shift()(Module); + } + }; + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[ptr]; + case 'i8': return HEAP8[ptr]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': abort('to do getValue(i64) use WASM_BIGINT'); + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + + var noExitRuntime = Module['noExitRuntime'] || true; + + var ptrToString = (ptr) => { + assert(typeof ptr === 'number'); + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + ptr >>>= 0; + return '0x' + ptr.toString(16).padStart(8, '0'); + }; + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[ptr] = value; break; + case 'i8': HEAP8[ptr] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': abort('to do setValue(i64) use WASM_BIGINT'); + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + + var stackRestore = (val) => __emscripten_stack_restore(val); + + var stackSave = () => _emscripten_stack_get_current(); + + var warnOnce = (text) => { + warnOnce.shown ||= {}; + if (!warnOnce.shown[text]) { + warnOnce.shown[text] = 1; + err(text); + } + }; + + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var endIdx = idx + maxBytesToRead; + + var str = ''; + while (!(idx >= endIdx)) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = heapOrArray[idx++]; + // If not building with TextDecoder enabled, we don't know the string + // length, so scan for \0 byte. + // If building with TextDecoder, we know exactly at what byte index the + // string ends, so checking for nulls here would be redundant. + if (!u0) return str; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + return str; + }; + + /** + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index (i.e. maxBytesToRead will not + * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing + * frequent uses of UTF8ToString() with and without maxBytesToRead may throw + * JS JIT optimizations off, so it is worth to consider consistently using one + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead) => { + assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`); + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; + }; + var ___assert_fail = (condition, filename, line, func) => { + abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); + }; + + class ExceptionInfo { + // excPtr - Thrown object pointer to wrap. Metadata pointer is calculated from it. + constructor(excPtr) { + this.excPtr = excPtr; + this.ptr = excPtr - 24; + } + + set_type(type) { + HEAPU32[(((this.ptr)+(4))>>2)] = type; + } + + get_type() { + return HEAPU32[(((this.ptr)+(4))>>2)]; + } + + set_destructor(destructor) { + HEAPU32[(((this.ptr)+(8))>>2)] = destructor; + } + + get_destructor() { + return HEAPU32[(((this.ptr)+(8))>>2)]; + } + + set_caught(caught) { + caught = caught ? 1 : 0; + HEAP8[(this.ptr)+(12)] = caught; + } + + get_caught() { + return HEAP8[(this.ptr)+(12)] != 0; + } + + set_rethrown(rethrown) { + rethrown = rethrown ? 1 : 0; + HEAP8[(this.ptr)+(13)] = rethrown; + } + + get_rethrown() { + return HEAP8[(this.ptr)+(13)] != 0; + } + + // Initialize native structure fields. Should be called once after allocated. + init(type, destructor) { + this.set_adjusted_ptr(0); + this.set_type(type); + this.set_destructor(destructor); + } + + set_adjusted_ptr(adjustedPtr) { + HEAPU32[(((this.ptr)+(16))>>2)] = adjustedPtr; + } + + get_adjusted_ptr() { + return HEAPU32[(((this.ptr)+(16))>>2)]; + } + + // Get pointer which is expected to be received by catch clause in C++ code. It may be adjusted + // when the pointer is casted to some of the exception object base classes (e.g. when virtual + // inheritance is used). When a pointer is thrown this method should return the thrown pointer + // itself. + get_exception_ptr() { + // Work around a fastcomp bug, this code is still included for some reason in a build without + // exceptions support. + var isPointer = ___cxa_is_pointer_type(this.get_type()); + if (isPointer) { + return HEAPU32[((this.excPtr)>>2)]; + } + var adjusted = this.get_adjusted_ptr(); + if (adjusted !== 0) return adjusted; + return this.excPtr; + } + } + + var exceptionLast = 0; + + var uncaughtExceptionCount = 0; + var ___cxa_throw = (ptr, type, destructor) => { + var info = new ExceptionInfo(ptr); + // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception. + info.init(type, destructor); + exceptionLast = ptr; + uncaughtExceptionCount++; + assert(false, 'Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.'); + }; + + var __embind_register_bigint = (primitiveType, name, size, minRange, maxRange) => {}; + + var embind_init_charCodes = () => { + var codes = new Array(256); + for (var i = 0; i < 256; ++i) { + codes[i] = String.fromCharCode(i); + } + embind_charCodes = codes; + }; + var embind_charCodes; + var readLatin1String = (ptr) => { + var ret = ""; + var c = ptr; + while (HEAPU8[c]) { + ret += embind_charCodes[HEAPU8[c++]]; + } + return ret; + }; + + var awaitingDependencies = { + }; + + var registeredTypes = { + }; + + var typeDependencies = { + }; + + var BindingError; + var throwBindingError = (message) => { throw new BindingError(message); }; + + + + + var InternalError; + var throwInternalError = (message) => { throw new InternalError(message); }; + var whenDependentTypesAreResolved = (myTypes, dependentTypes, getTypeConverters) => { + myTypes.forEach(function(type) { + typeDependencies[type] = dependentTypes; + }); + + function onComplete(typeConverters) { + var myTypeConverters = getTypeConverters(typeConverters); + if (myTypeConverters.length !== myTypes.length) { + throwInternalError('Mismatched type converter count'); + } + for (var i = 0; i < myTypes.length; ++i) { + registerType(myTypes[i], myTypeConverters[i]); + } + } + + var typeConverters = new Array(dependentTypes.length); + var unregisteredTypes = []; + var registered = 0; + dependentTypes.forEach((dt, i) => { + if (registeredTypes.hasOwnProperty(dt)) { + typeConverters[i] = registeredTypes[dt]; + } else { + unregisteredTypes.push(dt); + if (!awaitingDependencies.hasOwnProperty(dt)) { + awaitingDependencies[dt] = []; + } + awaitingDependencies[dt].push(() => { + typeConverters[i] = registeredTypes[dt]; + ++registered; + if (registered === unregisteredTypes.length) { + onComplete(typeConverters); + } + }); + } + }); + if (0 === unregisteredTypes.length) { + onComplete(typeConverters); + } + }; + /** @param {Object=} options */ + function sharedRegisterType(rawType, registeredInstance, options = {}) { + var name = registeredInstance.name; + if (!rawType) { + throwBindingError(`type "${name}" must have a positive integer typeid pointer`); + } + if (registeredTypes.hasOwnProperty(rawType)) { + if (options.ignoreDuplicateRegistrations) { + return; + } else { + throwBindingError(`Cannot register type '${name}' twice`); + } + } + + registeredTypes[rawType] = registeredInstance; + delete typeDependencies[rawType]; + + if (awaitingDependencies.hasOwnProperty(rawType)) { + var callbacks = awaitingDependencies[rawType]; + delete awaitingDependencies[rawType]; + callbacks.forEach((cb) => cb()); + } + } + /** @param {Object=} options */ + function registerType(rawType, registeredInstance, options = {}) { + if (!('argPackAdvance' in registeredInstance)) { + throw new TypeError('registerType registeredInstance requires argPackAdvance'); + } + return sharedRegisterType(rawType, registeredInstance, options); + } + + var GenericWireTypeSize = 8; + /** @suppress {globalThis} */ + var __embind_register_bool = (rawType, name, trueValue, falseValue) => { + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': function(wt) { + // ambiguous emscripten ABI: sometimes return values are + // true or false, and sometimes integers (0 or 1) + return !!wt; + }, + 'toWireType': function(destructors, o) { + return o ? trueValue : falseValue; + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': function(pointer) { + return this['fromWireType'](HEAPU8[pointer]); + }, + destructorFunction: null, // This type does not need a destructor + }); + }; + + + var emval_freelist = []; + + var emval_handles = []; + var __emval_decref = (handle) => { + if (handle > 9 && 0 === --emval_handles[handle + 1]) { + assert(emval_handles[handle] !== undefined, `Decref for unallocated handle.`); + emval_handles[handle] = undefined; + emval_freelist.push(handle); + } + }; + + + + + + var count_emval_handles = () => { + return emval_handles.length / 2 - 5 - emval_freelist.length; + }; + + var init_emval = () => { + // reserve 0 and some special values. These never get de-allocated. + emval_handles.push( + 0, 1, + undefined, 1, + null, 1, + true, 1, + false, 1, + ); + assert(emval_handles.length === 5 * 2); + Module['count_emval_handles'] = count_emval_handles; + }; + var Emval = { + toValue:(handle) => { + if (!handle) { + throwBindingError('Cannot use deleted val. handle = ' + handle); + } + // handle 2 is supposed to be `undefined`. + assert(handle === 2 || emval_handles[handle] !== undefined && handle % 2 === 0, `invalid handle: ${handle}`); + return emval_handles[handle]; + }, + toHandle:(value) => { + switch (value) { + case undefined: return 2; + case null: return 4; + case true: return 6; + case false: return 8; + default:{ + const handle = emval_freelist.pop() || emval_handles.length; + emval_handles[handle] = value; + emval_handles[handle + 1] = 1; + return handle; + } + } + }, + }; + + /** @suppress {globalThis} */ + function readPointer(pointer) { + return this['fromWireType'](HEAPU32[((pointer)>>2)]); + } + + var EmValType = { + name: 'emscripten::val', + 'fromWireType': (handle) => { + var rv = Emval.toValue(handle); + __emval_decref(handle); + return rv; + }, + 'toWireType': (destructors, value) => Emval.toHandle(value), + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, + destructorFunction: null, // This type does not need a destructor + + // TODO: do we need a deleteObject here? write a test where + // emval is passed into JS via an interface + }; + var __embind_register_emval = (rawType) => registerType(rawType, EmValType); + + var embindRepr = (v) => { + if (v === null) { + return 'null'; + } + var t = typeof v; + if (t === 'object' || t === 'array' || t === 'function') { + return v.toString(); + } else { + return '' + v; + } + }; + + var floatReadValueFromPointer = (name, width) => { + switch (width) { + case 4: return function(pointer) { + return this['fromWireType'](HEAPF32[((pointer)>>2)]); + }; + case 8: return function(pointer) { + return this['fromWireType'](HEAPF64[((pointer)>>3)]); + }; + default: + throw new TypeError(`invalid float width (${width}): ${name}`); + } + }; + + + var __embind_register_float = (rawType, name, size) => { + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': (value) => value, + 'toWireType': (destructors, value) => { + if (typeof value != "number" && typeof value != "boolean") { + throw new TypeError(`Cannot convert ${embindRepr(value)} to ${this.name}`); + } + // The VM will perform JS to Wasm value conversion, according to the spec: + // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue + return value; + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': floatReadValueFromPointer(name, size), + destructorFunction: null, // This type does not need a destructor + }); + }; + + var createNamedFunction = (name, body) => Object.defineProperty(body, 'name', { + value: name + }); + + var runDestructors = (destructors) => { + while (destructors.length) { + var ptr = destructors.pop(); + var del = destructors.pop(); + del(ptr); + } + }; + + + function usesDestructorStack(argTypes) { + // Skip return value at index 0 - it's not deleted here. + for (var i = 1; i < argTypes.length; ++i) { + // The type does not define a destructor function - must use dynamic stack + if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) { + return true; + } + } + return false; + } + function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc, /** boolean= */ isAsync) { + // humanName: a human-readable string name for the function to be generated. + // argTypes: An array that contains the embind type objects for all types in the function signature. + // argTypes[0] is the type object for the function return value. + // argTypes[1] is the type object for function this object/class type, or null if not crafting an invoker for a class method. + // argTypes[2...] are the actual function parameters. + // classType: The embind type object for the class to be bound, or null if this is not a method of a class. + // cppInvokerFunc: JS Function object to the C++-side function that interops into C++ code. + // cppTargetFunc: Function pointer (an integer to FUNCTION_TABLE) to the target C++ function the cppInvokerFunc will end up calling. + // isAsync: Optional. If true, returns an async function. Async bindings are only supported with JSPI. + var argCount = argTypes.length; + + if (argCount < 2) { + throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!"); + } + + assert(!isAsync, 'Async bindings are only supported with JSPI.'); + + var isClassMethodFunc = (argTypes[1] !== null && classType !== null); + + // Free functions with signature "void function()" do not need an invoker that marshalls between wire types. + // TODO: This omits argument count check - enable only at -O3 or similar. + // if (ENABLE_UNSAFE_OPTS && argCount == 2 && argTypes[0].name == "void" && !isClassMethodFunc) { + // return FUNCTION_TABLE[fn]; + // } + + // Determine if we need to use a dynamic stack to store the destructors for the function parameters. + // TODO: Remove this completely once all function invokers are being dynamically generated. + var needsDestructorStack = usesDestructorStack(argTypes); + + var returns = (argTypes[0].name !== "void"); + + var expectedArgCount = argCount - 2; + var argsWired = new Array(expectedArgCount); + var invokerFuncArgs = []; + var destructors = []; + var invokerFn = function(...args) { + if (args.length !== expectedArgCount) { + throwBindingError(`function ${humanName} called with ${args.length} arguments, expected ${expectedArgCount}`); + } + destructors.length = 0; + var thisWired; + invokerFuncArgs.length = isClassMethodFunc ? 2 : 1; + invokerFuncArgs[0] = cppTargetFunc; + if (isClassMethodFunc) { + thisWired = argTypes[1]['toWireType'](destructors, this); + invokerFuncArgs[1] = thisWired; + } + for (var i = 0; i < expectedArgCount; ++i) { + argsWired[i] = argTypes[i + 2]['toWireType'](destructors, args[i]); + invokerFuncArgs.push(argsWired[i]); + } + + var rv = cppInvokerFunc(...invokerFuncArgs); + + function onDone(rv) { + if (needsDestructorStack) { + runDestructors(destructors); + } else { + for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; i++) { + var param = i === 1 ? thisWired : argsWired[i - 2]; + if (argTypes[i].destructorFunction !== null) { + argTypes[i].destructorFunction(param); + } + } + } + + if (returns) { + return argTypes[0]['fromWireType'](rv); + } + } + + return onDone(rv); + }; + return createNamedFunction(humanName, invokerFn); + } + + var ensureOverloadTable = (proto, methodName, humanName) => { + if (undefined === proto[methodName].overloadTable) { + var prevFunc = proto[methodName]; + // Inject an overload resolver function that routes to the appropriate overload based on the number of arguments. + proto[methodName] = function(...args) { + // TODO This check can be removed in -O3 level "unsafe" optimizations. + if (!proto[methodName].overloadTable.hasOwnProperty(args.length)) { + throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`); + } + return proto[methodName].overloadTable[args.length].apply(this, args); + }; + // Move the previous function into the overload table. + proto[methodName].overloadTable = []; + proto[methodName].overloadTable[prevFunc.argCount] = prevFunc; + } + }; + + /** @param {number=} numArguments */ + var exposePublicSymbol = (name, value, numArguments) => { + if (Module.hasOwnProperty(name)) { + if (undefined === numArguments || (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments])) { + throwBindingError(`Cannot register public name '${name}' twice`); + } + + // We are exposing a function with the same name as an existing function. Create an overload table and a function selector + // that routes between the two. + ensureOverloadTable(Module, name, name); + if (Module.hasOwnProperty(numArguments)) { + throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`); + } + // Add the new function into the overload table. + Module[name].overloadTable[numArguments] = value; + } + else { + Module[name] = value; + if (undefined !== numArguments) { + Module[name].numArguments = numArguments; + } + } + }; + + var heap32VectorToArray = (count, firstElement) => { + var array = []; + for (var i = 0; i < count; i++) { + // TODO(https://github.com/emscripten-core/emscripten/issues/17310): + // Find a way to hoist the `>> 2` or `>> 3` out of this loop. + array.push(HEAPU32[(((firstElement)+(i * 4))>>2)]); + } + return array; + }; + + + /** @param {number=} numArguments */ + var replacePublicSymbol = (name, value, numArguments) => { + if (!Module.hasOwnProperty(name)) { + throwInternalError('Replacing nonexistent public symbol'); + } + // If there's an overload table for this symbol, replace the symbol in the overload table instead. + if (undefined !== Module[name].overloadTable && undefined !== numArguments) { + Module[name].overloadTable[numArguments] = value; + } + else { + Module[name] = value; + Module[name].argCount = numArguments; + } + }; + + + + var dynCallLegacy = (sig, ptr, args) => { + sig = sig.replace(/p/g, 'i') + assert(('dynCall_' + sig) in Module, `bad function pointer type - dynCall function not found for sig '${sig}'`); + if (args?.length) { + // j (64-bit integer) must be passed in as two numbers [low 32, high 32]. + assert(args.length === sig.substring(1).replace(/j/g, '--').length); + } else { + assert(sig.length == 1); + } + var f = Module['dynCall_' + sig]; + return f(ptr, ...args); + }; + + var wasmTableMirror = []; + + var wasmTable; + var getWasmTableEntry = (funcPtr) => { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); + } + assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!'); + return func; + }; + + var dynCall = (sig, ptr, args = []) => { + // Without WASM_BIGINT support we cannot directly call function with i64 as + // part of their signature, so we rely on the dynCall functions generated by + // wasm-emscripten-finalize + if (sig.includes('j')) { + return dynCallLegacy(sig, ptr, args); + } + assert(getWasmTableEntry(ptr), `missing table entry in dynCall: ${ptr}`); + var rtn = getWasmTableEntry(ptr)(...args); + return rtn; + }; + var getDynCaller = (sig, ptr) => { + assert(sig.includes('j') || sig.includes('p'), 'getDynCaller should only be called with i64 sigs') + return (...args) => dynCall(sig, ptr, args); + }; + + + var embind__requireFunction = (signature, rawFunction) => { + signature = readLatin1String(signature); + + function makeDynCaller() { + if (signature.includes('j')) { + return getDynCaller(signature, rawFunction); + } + return getWasmTableEntry(rawFunction); + } + + var fp = makeDynCaller(); + if (typeof fp != "function") { + throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`); + } + return fp; + }; + + + + var extendError = (baseErrorType, errorName) => { + var errorClass = createNamedFunction(errorName, function(message) { + this.name = errorName; + this.message = message; + + var stack = (new Error(message)).stack; + if (stack !== undefined) { + this.stack = this.toString() + '\n' + + stack.replace(/^Error(:[^\n]*)?\n/, ''); + } + }); + errorClass.prototype = Object.create(baseErrorType.prototype); + errorClass.prototype.constructor = errorClass; + errorClass.prototype.toString = function() { + if (this.message === undefined) { + return this.name; + } else { + return `${this.name}: ${this.message}`; + } + }; + + return errorClass; + }; + var UnboundTypeError; + + + + var getTypeName = (type) => { + var ptr = ___getTypeName(type); + var rv = readLatin1String(ptr); + _free(ptr); + return rv; + }; + var throwUnboundTypeError = (message, types) => { + var unboundTypes = []; + var seen = {}; + function visit(type) { + if (seen[type]) { + return; + } + if (registeredTypes[type]) { + return; + } + if (typeDependencies[type]) { + typeDependencies[type].forEach(visit); + return; + } + unboundTypes.push(type); + seen[type] = true; + } + types.forEach(visit); + + throw new UnboundTypeError(`${message}: ` + unboundTypes.map(getTypeName).join([', '])); + }; + + + var getFunctionName = (signature) => { + signature = signature.trim(); + const argsIndex = signature.indexOf("("); + if (argsIndex !== -1) { + assert(signature[signature.length - 1] == ")", "Parentheses for argument names should match."); + return signature.substr(0, argsIndex); + } else { + return signature; + } + }; + var __embind_register_function = (name, argCount, rawArgTypesAddr, signature, rawInvoker, fn, isAsync) => { + var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); + name = readLatin1String(name); + name = getFunctionName(name); + + rawInvoker = embind__requireFunction(signature, rawInvoker); + + exposePublicSymbol(name, function() { + throwUnboundTypeError(`Cannot call ${name} due to unbound types`, argTypes); + }, argCount - 1); + + whenDependentTypesAreResolved([], argTypes, (argTypes) => { + var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */); + replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn, isAsync), argCount - 1); + return []; + }); + }; + + + var integerReadValueFromPointer = (name, width, signed) => { + // integers are quite common, so generate very specialized functions + switch (width) { + case 1: return signed ? + (pointer) => HEAP8[pointer] : + (pointer) => HEAPU8[pointer]; + case 2: return signed ? + (pointer) => HEAP16[((pointer)>>1)] : + (pointer) => HEAPU16[((pointer)>>1)] + case 4: return signed ? + (pointer) => HEAP32[((pointer)>>2)] : + (pointer) => HEAPU32[((pointer)>>2)] + default: + throw new TypeError(`invalid integer width (${width}): ${name}`); + } + }; + + + /** @suppress {globalThis} */ + var __embind_register_integer = (primitiveType, name, size, minRange, maxRange) => { + name = readLatin1String(name); + // LLVM doesn't have signed and unsigned 32-bit types, so u32 literals come + // out as 'i32 -1'. Always treat those as max u32. + if (maxRange === -1) { + maxRange = 4294967295; + } + + var fromWireType = (value) => value; + + if (minRange === 0) { + var bitshift = 32 - 8*size; + fromWireType = (value) => (value << bitshift) >>> bitshift; + } + + var isUnsignedType = (name.includes('unsigned')); + var checkAssertions = (value, toTypeName) => { + if (typeof value != "number" && typeof value != "boolean") { + throw new TypeError(`Cannot convert "${embindRepr(value)}" to ${toTypeName}`); + } + if (value < minRange || value > maxRange) { + throw new TypeError(`Passing a number "${embindRepr(value)}" from JS side to C/C++ side to an argument of type "${name}", which is outside the valid range [${minRange}, ${maxRange}]!`); + } + } + var toWireType; + if (isUnsignedType) { + toWireType = function(destructors, value) { + checkAssertions(value, this.name); + return value >>> 0; + } + } else { + toWireType = function(destructors, value) { + checkAssertions(value, this.name); + // The VM will perform JS to Wasm value conversion, according to the spec: + // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue + return value; + } + } + registerType(primitiveType, { + name, + 'fromWireType': fromWireType, + 'toWireType': toWireType, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': integerReadValueFromPointer(name, size, minRange !== 0), + destructorFunction: null, // This type does not need a destructor + }); + }; + + + var __embind_register_memory_view = (rawType, dataTypeIndex, name) => { + var typeMapping = [ + Int8Array, + Uint8Array, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + ]; + + var TA = typeMapping[dataTypeIndex]; + + function decodeMemoryView(handle) { + var size = HEAPU32[((handle)>>2)]; + var data = HEAPU32[(((handle)+(4))>>2)]; + return new TA(HEAP8.buffer, data, size); + } + + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': decodeMemoryView, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': decodeMemoryView, + }, { + ignoreDuplicateRegistrations: true, + }); + }; + + + + + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`); + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.charCodeAt(i); // possibly a lead surrogate + if (u >= 0xD800 && u <= 0xDFFF) { + var u1 = str.charCodeAt(++i); + u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); + } + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; + }; + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + }; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var c = str.charCodeAt(i); // possibly a lead surrogate + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + + + + var __embind_register_std_string = (rawType, name) => { + name = readLatin1String(name); + var stdStringIsUTF8 + //process only std::string bindings with UTF8 support, in contrast to e.g. std::basic_string + = (name === "std::string"); + + registerType(rawType, { + name, + // For some method names we use string keys here since they are part of + // the public/external API and/or used by the runtime-generated code. + 'fromWireType'(value) { + var length = HEAPU32[((value)>>2)]; + var payload = value + 4; + + var str; + if (stdStringIsUTF8) { + var decodeStartPtr = payload; + // Looping here to support possible embedded '0' bytes + for (var i = 0; i <= length; ++i) { + var currentBytePtr = payload + i; + if (i == length || HEAPU8[currentBytePtr] == 0) { + var maxRead = currentBytePtr - decodeStartPtr; + var stringSegment = UTF8ToString(decodeStartPtr, maxRead); + if (str === undefined) { + str = stringSegment; + } else { + str += String.fromCharCode(0); + str += stringSegment; + } + decodeStartPtr = currentBytePtr + 1; + } + } + } else { + var a = new Array(length); + for (var i = 0; i < length; ++i) { + a[i] = String.fromCharCode(HEAPU8[payload + i]); + } + str = a.join(''); + } + + _free(value); + + return str; + }, + 'toWireType'(destructors, value) { + if (value instanceof ArrayBuffer) { + value = new Uint8Array(value); + } + + var length; + var valueIsOfTypeString = (typeof value == 'string'); + + if (!(valueIsOfTypeString || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Int8Array)) { + throwBindingError('Cannot pass non-string to std::string'); + } + if (stdStringIsUTF8 && valueIsOfTypeString) { + length = lengthBytesUTF8(value); + } else { + length = value.length; + } + + // assumes POINTER_SIZE alignment + var base = _malloc(4 + length + 1); + var ptr = base + 4; + HEAPU32[((base)>>2)] = length; + if (stdStringIsUTF8 && valueIsOfTypeString) { + stringToUTF8(value, ptr, length + 1); + } else { + if (valueIsOfTypeString) { + for (var i = 0; i < length; ++i) { + var charCode = value.charCodeAt(i); + if (charCode > 255) { + _free(ptr); + throwBindingError('String has UTF-16 code units that do not fit in 8 bits'); + } + HEAPU8[ptr + i] = charCode; + } + } else { + for (var i = 0; i < length; ++i) { + HEAPU8[ptr + i] = value[i]; + } + } + } + + if (destructors !== null) { + destructors.push(_free, base); + } + return base; + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, + destructorFunction(ptr) { + _free(ptr); + }, + }); + }; + + + + + var UTF16ToString = (ptr, maxBytesToRead) => { + assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!'); + + // Fallback: decode without UTF16Decoder + var str = ''; + + // If maxBytesToRead is not passed explicitly, it will be undefined, and the + // for-loop's condition will always evaluate to true. The loop is then + // terminated on the first null char. + for (var i = 0; !(i >= maxBytesToRead / 2); ++i) { + var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; + if (codeUnit == 0) break; + // fromCharCode constructs a character from a UTF-16 code unit, so we can + // pass the UTF16 string right through. + str += String.fromCharCode(codeUnit); + } + + return str; + }; + + var stringToUTF16 = (str, outPtr, maxBytesToWrite) => { + assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!'); + assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. + maxBytesToWrite ??= 0x7FFFFFFF; + if (maxBytesToWrite < 2) return 0; + maxBytesToWrite -= 2; // Null terminator. + var startPtr = outPtr; + var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; + for (var i = 0; i < numCharsToWrite; ++i) { + // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + HEAP16[((outPtr)>>1)] = codeUnit; + outPtr += 2; + } + // Null-terminate the pointer to the HEAP. + HEAP16[((outPtr)>>1)] = 0; + return outPtr - startPtr; + }; + + var lengthBytesUTF16 = (str) => { + return str.length*2; + }; + + var UTF32ToString = (ptr, maxBytesToRead) => { + assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!'); + var i = 0; + + var str = ''; + // If maxBytesToRead is not passed explicitly, it will be undefined, and this + // will always evaluate to true. This saves on code size. + while (!(i >= maxBytesToRead / 4)) { + var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; + if (utf32 == 0) break; + ++i; + // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + if (utf32 >= 0x10000) { + var ch = utf32 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } else { + str += String.fromCharCode(utf32); + } + } + return str; + }; + + var stringToUTF32 = (str, outPtr, maxBytesToWrite) => { + assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!'); + assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. + maxBytesToWrite ??= 0x7FFFFFFF; + if (maxBytesToWrite < 4) return 0; + var startPtr = outPtr; + var endPtr = startPtr + maxBytesToWrite - 4; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { + var trailSurrogate = str.charCodeAt(++i); + codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); + } + HEAP32[((outPtr)>>2)] = codeUnit; + outPtr += 4; + if (outPtr + 4 > endPtr) break; + } + // Null-terminate the pointer to the HEAP. + HEAP32[((outPtr)>>2)] = 0; + return outPtr - startPtr; + }; + + var lengthBytesUTF32 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var codeUnit = str.charCodeAt(i); + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate. + len += 4; + } + + return len; + }; + var __embind_register_std_wstring = (rawType, charSize, name) => { + name = readLatin1String(name); + var decodeString, encodeString, readCharAt, lengthBytesUTF; + if (charSize === 2) { + decodeString = UTF16ToString; + encodeString = stringToUTF16; + lengthBytesUTF = lengthBytesUTF16; + readCharAt = (pointer) => HEAPU16[((pointer)>>1)]; + } else if (charSize === 4) { + decodeString = UTF32ToString; + encodeString = stringToUTF32; + lengthBytesUTF = lengthBytesUTF32; + readCharAt = (pointer) => HEAPU32[((pointer)>>2)]; + } + registerType(rawType, { + name, + 'fromWireType': (value) => { + // Code mostly taken from _embind_register_std_string fromWireType + var length = HEAPU32[((value)>>2)]; + var str; + + var decodeStartPtr = value + 4; + // Looping here to support possible embedded '0' bytes + for (var i = 0; i <= length; ++i) { + var currentBytePtr = value + 4 + i * charSize; + if (i == length || readCharAt(currentBytePtr) == 0) { + var maxReadBytes = currentBytePtr - decodeStartPtr; + var stringSegment = decodeString(decodeStartPtr, maxReadBytes); + if (str === undefined) { + str = stringSegment; + } else { + str += String.fromCharCode(0); + str += stringSegment; + } + decodeStartPtr = currentBytePtr + charSize; + } + } + + _free(value); + + return str; + }, + 'toWireType': (destructors, value) => { + if (!(typeof value == 'string')) { + throwBindingError(`Cannot pass non-string to C++ string type ${name}`); + } + + // assumes POINTER_SIZE alignment + var length = lengthBytesUTF(value); + var ptr = _malloc(4 + length + charSize); + HEAPU32[((ptr)>>2)] = length / charSize; + + encodeString(value, ptr + 4, length + charSize); + + if (destructors !== null) { + destructors.push(_free, ptr); + } + return ptr; + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, + destructorFunction(ptr) { + _free(ptr); + } + }); + }; + + + var __embind_register_void = (rawType, name) => { + name = readLatin1String(name); + registerType(rawType, { + isVoid: true, // void return values can be optimized out sometimes + name, + 'argPackAdvance': 0, + 'fromWireType': () => undefined, + // TODO: assert if anything else is given? + 'toWireType': (destructors, o) => undefined, + }); + }; + + var __emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); + + var emval_methodCallers = []; + + var __emval_call = (caller, handle, destructorsRef, args) => { + caller = emval_methodCallers[caller]; + handle = Emval.toValue(handle); + return caller(null, handle, destructorsRef, args); + }; + + + + var emval_symbols = { + }; + + var getStringOrSymbol = (address) => { + var symbol = emval_symbols[address]; + if (symbol === undefined) { + return readLatin1String(address); + } + return symbol; + }; + + var emval_get_global = () => { + if (typeof globalThis == 'object') { + return globalThis; + } + function testGlobal(obj) { + obj['$$$embind_global$$$'] = obj; + var success = typeof $$$embind_global$$$ == 'object' && obj['$$$embind_global$$$'] == obj; + if (!success) { + delete obj['$$$embind_global$$$']; + } + return success; + } + if (typeof $$$embind_global$$$ == 'object') { + return $$$embind_global$$$; + } + if (typeof global == 'object' && testGlobal(global)) { + $$$embind_global$$$ = global; + } else if (typeof self == 'object' && testGlobal(self)) { + $$$embind_global$$$ = self; // This works for both "window" and "self" (Web Workers) global objects + } + if (typeof $$$embind_global$$$ == 'object') { + return $$$embind_global$$$; + } + throw Error('unable to get global object.'); + }; + var __emval_get_global = (name) => { + if (name===0) { + return Emval.toHandle(emval_get_global()); + } else { + name = getStringOrSymbol(name); + return Emval.toHandle(emval_get_global()[name]); + } + }; + + var emval_addMethodCaller = (caller) => { + var id = emval_methodCallers.length; + emval_methodCallers.push(caller); + return id; + }; + + + + var requireRegisteredType = (rawType, humanName) => { + var impl = registeredTypes[rawType]; + if (undefined === impl) { + throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`); + } + return impl; + }; + var emval_lookupTypes = (argCount, argTypes) => { + var a = new Array(argCount); + for (var i = 0; i < argCount; ++i) { + a[i] = requireRegisteredType(HEAPU32[(((argTypes)+(i * 4))>>2)], + "parameter " + i); + } + return a; + }; + + + var reflectConstruct = Reflect.construct; + + var emval_returnValue = (returnType, destructorsRef, handle) => { + var destructors = []; + var result = returnType['toWireType'](destructors, handle); + if (destructors.length) { + // void, primitives and any other types w/o destructors don't need to allocate a handle + HEAPU32[((destructorsRef)>>2)] = Emval.toHandle(destructors); + } + return result; + }; + var __emval_get_method_caller = (argCount, argTypes, kind) => { + var types = emval_lookupTypes(argCount, argTypes); + var retType = types.shift(); + argCount--; // remove the shifted off return type + + var argN = new Array(argCount); + var invokerFunction = (obj, func, destructorsRef, args) => { + var offset = 0; + for (var i = 0; i < argCount; ++i) { + argN[i] = types[i]['readValueFromPointer'](args + offset); + offset += types[i]['argPackAdvance']; + } + var rv = kind === /* CONSTRUCTOR */ 1 ? reflectConstruct(func, argN) : func.apply(obj, argN); + return emval_returnValue(retType, destructorsRef, rv); + }; + var functionName = `methodCaller<(${types.map(t => t.name).join(', ')}) => ${retType.name}>`; + return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction)); + }; + + + + var __emval_run_destructors = (handle) => { + var destructors = Emval.toValue(handle); + runDestructors(destructors); + __emval_decref(handle); + }; + + var _abort = () => { + abort('native code called abort()'); + }; + + var getHeapMax = () => + // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate + // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side + // for any code that deals with heap sizes, which would require special + // casing all heap size related code to treat 0 specially. + 2147483648; + + var growMemory = (size) => { + var b = wasmMemory.buffer; + var pages = (size - b.byteLength + 65535) / 65536; + try { + // round size grow request up to wasm page size (fixed 64KB per spec) + wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size + updateMemoryViews(); + return 1 /*success*/; + } catch(e) { + err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`); + } + // implicit 0 return to save code size (caller will cast "undefined" into 0 + // anyhow) + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + requestedSize >>>= 0; + // With multithreaded builds, races can happen (another thread might increase the size + // in between), so return a failure, and let the caller retry. + assert(requestedSize > oldSize); + + // Memory resize rules: + // 1. Always increase heap size to at least the requested size, rounded up + // to next page multiple. + // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap + // geometrically: increase the heap size according to + // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most + // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB). + // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap + // linearly: increase the heap size by at least + // MEMORY_GROWTH_LINEAR_STEP bytes. + // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by + // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest + // 4. If we were unable to allocate as much memory, it may be due to + // over-eager decision to excessively reserve due to (3) above. + // Hence if an allocation fails, cut down on the amount of excess + // growth, in an attempt to succeed to perform a smaller allocation. + + // A limit is set for how much we can grow. We should not exceed that + // (the wasm binary specifies it, so if we tried, we'd fail anyhow). + var maxHeapSize = getHeapMax(); + if (requestedSize > maxHeapSize) { + err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`); + return false; + } + + var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple; + + // Loop through potential heap size increases. If we attempt a too eager + // reservation that fails, cut down on the attempted size and reserve a + // smaller bump instead. (max 3 times, chosen somewhat arbitrarily) + for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { + var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth + // but limit overreserving (default to capping at +96MB overgrowth at most) + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 ); + + var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); + + var replacement = growMemory(newSize); + if (replacement) { + + return true; + } + } + err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`); + return false; + }; + + var SYSCALLS = { + varargs:undefined, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + }; + var _fd_close = (fd) => { + abort('fd_close called without SYSCALLS_REQUIRE_FILESYSTEM'); + }; + + var convertI32PairToI53Checked = (lo, hi) => { + assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32 + assert(hi === (hi|0)); // hi should be a i32 + return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; + }; + function _fd_seek(fd,offset_low, offset_high,whence,newOffset) { + var offset = convertI32PairToI53Checked(offset_low, offset_high); + + + return 70; + ; + } + + var printCharBuffers = [null,[],[]]; + + var printChar = (stream, curr) => { + var buffer = printCharBuffers[stream]; + assert(buffer); + if (curr === 0 || curr === 10) { + (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); + buffer.length = 0; + } else { + buffer.push(curr); + } + }; + + var flush_NO_FILESYSTEM = () => { + // flush anything remaining in the buffers during shutdown + _fflush(0); + if (printCharBuffers[1].length) printChar(1, 10); + if (printCharBuffers[2].length) printChar(2, 10); + }; + + + var _fd_write = (fd, iov, iovcnt, pnum) => { + // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 + var num = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + for (var j = 0; j < len; j++) { + printChar(fd, HEAPU8[ptr+j]); + } + num += len; + } + HEAPU32[((pnum)>>2)] = num; + return 0; + }; +embind_init_charCodes(); +BindingError = Module['BindingError'] = class BindingError extends Error { constructor(message) { super(message); this.name = 'BindingError'; }}; +InternalError = Module['InternalError'] = class InternalError extends Error { constructor(message) { super(message); this.name = 'InternalError'; }}; +init_emval();; +UnboundTypeError = Module['UnboundTypeError'] = extendError(Error, 'UnboundTypeError');; +function checkIncomingModuleAPI() { + ignoredModuleProp('fetchSettings'); +} +var wasmImports = { + /** @export */ + __assert_fail: ___assert_fail, + /** @export */ + __cxa_throw: ___cxa_throw, + /** @export */ + _embind_register_bigint: __embind_register_bigint, + /** @export */ + _embind_register_bool: __embind_register_bool, + /** @export */ + _embind_register_emval: __embind_register_emval, + /** @export */ + _embind_register_float: __embind_register_float, + /** @export */ + _embind_register_function: __embind_register_function, + /** @export */ + _embind_register_integer: __embind_register_integer, + /** @export */ + _embind_register_memory_view: __embind_register_memory_view, + /** @export */ + _embind_register_std_string: __embind_register_std_string, + /** @export */ + _embind_register_std_wstring: __embind_register_std_wstring, + /** @export */ + _embind_register_void: __embind_register_void, + /** @export */ + _emscripten_memcpy_js: __emscripten_memcpy_js, + /** @export */ + _emval_call: __emval_call, + /** @export */ + _emval_decref: __emval_decref, + /** @export */ + _emval_get_global: __emval_get_global, + /** @export */ + _emval_get_method_caller: __emval_get_method_caller, + /** @export */ + _emval_run_destructors: __emval_run_destructors, + /** @export */ + abort: _abort, + /** @export */ + emscripten_resize_heap: _emscripten_resize_heap, + /** @export */ + fd_close: _fd_close, + /** @export */ + fd_seek: _fd_seek, + /** @export */ + fd_write: _fd_write +}; +var wasmExports = createWasm(); +var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors', 0); +var ___getTypeName = createExportWrapper('__getTypeName', 1); +var _free = createExportWrapper('free', 1); +var _malloc = createExportWrapper('malloc', 1); +var _fflush = createExportWrapper('fflush', 1); +var _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports['emscripten_stack_init'])(); +var _emscripten_stack_get_free = () => (_emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'])(); +var _emscripten_stack_get_base = () => (_emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'])(); +var _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'])(); +var __emscripten_stack_restore = (a0) => (__emscripten_stack_restore = wasmExports['_emscripten_stack_restore'])(a0); +var __emscripten_stack_alloc = (a0) => (__emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc'])(a0); +var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])(); +var ___cxa_increment_exception_refcount = createExportWrapper('__cxa_increment_exception_refcount', 1); +var ___cxa_is_pointer_type = createExportWrapper('__cxa_is_pointer_type', 1); +var dynCall_jiji = Module['dynCall_jiji'] = createExportWrapper('dynCall_jiji', 5); + + +// include: postamble.js +// === Auto-generated postamble setup entry stuff === + +var missingLibrarySymbols = [ + 'writeI53ToI64', + 'writeI53ToI64Clamped', + 'writeI53ToI64Signaling', + 'writeI53ToU64Clamped', + 'writeI53ToU64Signaling', + 'readI53FromI64', + 'readI53FromU64', + 'convertI32PairToI53', + 'convertU32PairToI53', + 'stackAlloc', + 'getTempRet0', + 'setTempRet0', + 'zeroMemory', + 'exitJS', + 'isLeapYear', + 'ydayFromDate', + 'arraySum', + 'addDays', + 'inetPton4', + 'inetNtop4', + 'inetPton6', + 'inetNtop6', + 'readSockaddr', + 'writeSockaddr', + 'initRandomFill', + 'randomFill', + 'emscriptenLog', + 'readEmAsmArgs', + 'jstoi_q', + 'getExecutableName', + 'listenOnce', + 'autoResumeAudioContext', + 'handleException', + 'keepRuntimeAlive', + 'runtimeKeepalivePush', + 'runtimeKeepalivePop', + 'callUserCallback', + 'maybeExit', + 'asmjsMangle', + 'asyncLoad', + 'alignMemory', + 'mmapAlloc', + 'HandleAllocator', + 'getNativeTypeSize', + 'STACK_SIZE', + 'STACK_ALIGN', + 'POINTER_SIZE', + 'ASSERTIONS', + 'getCFunc', + 'ccall', + 'cwrap', + 'uleb128Encode', + 'sigToWasmTypes', + 'generateFuncType', + 'convertJsFunctionToWasm', + 'getEmptyTableSlot', + 'updateTableMap', + 'getFunctionAddress', + 'addFunction', + 'removeFunction', + 'reallyNegative', + 'unSign', + 'strLen', + 'reSign', + 'formatString', + 'intArrayFromString', + 'intArrayToString', + 'AsciiToString', + 'stringToAscii', + 'stringToNewUTF8', + 'stringToUTF8OnStack', + 'writeArrayToMemory', + 'registerKeyEventCallback', + 'maybeCStringToJsString', + 'findEventTarget', + 'getBoundingClientRect', + 'fillMouseEventData', + 'registerMouseEventCallback', + 'registerWheelEventCallback', + 'registerUiEventCallback', + 'registerFocusEventCallback', + 'fillDeviceOrientationEventData', + 'registerDeviceOrientationEventCallback', + 'fillDeviceMotionEventData', + 'registerDeviceMotionEventCallback', + 'screenOrientation', + 'fillOrientationChangeEventData', + 'registerOrientationChangeEventCallback', + 'fillFullscreenChangeEventData', + 'registerFullscreenChangeEventCallback', + 'JSEvents_requestFullscreen', + 'JSEvents_resizeCanvasForFullscreen', + 'registerRestoreOldStyle', + 'hideEverythingExceptGivenElement', + 'restoreHiddenElements', + 'setLetterbox', + 'softFullscreenResizeWebGLRenderTarget', + 'doRequestFullscreen', + 'fillPointerlockChangeEventData', + 'registerPointerlockChangeEventCallback', + 'registerPointerlockErrorEventCallback', + 'requestPointerLock', + 'fillVisibilityChangeEventData', + 'registerVisibilityChangeEventCallback', + 'registerTouchEventCallback', + 'fillGamepadEventData', + 'registerGamepadEventCallback', + 'registerBeforeUnloadEventCallback', + 'fillBatteryEventData', + 'battery', + 'registerBatteryEventCallback', + 'setCanvasElementSize', + 'getCanvasElementSize', + 'jsStackTrace', + 'getCallstack', + 'convertPCtoSourceLocation', + 'getEnvStrings', + 'checkWasiClock', + 'wasiRightsToMuslOFlags', + 'wasiOFlagsToMuslOFlags', + 'createDyncallWrapper', + 'safeSetTimeout', + 'setImmediateWrapped', + 'clearImmediateWrapped', + 'polyfillSetImmediate', + 'getPromise', + 'makePromise', + 'idsToPromises', + 'makePromiseCallback', + 'findMatchingCatch', + 'Browser_asyncPrepareDataCounter', + 'setMainLoop', + 'getSocketFromFD', + 'getSocketAddress', + 'heapObjectForWebGLType', + 'toTypedArrayIndex', + 'webgl_enable_ANGLE_instanced_arrays', + 'webgl_enable_OES_vertex_array_object', + 'webgl_enable_WEBGL_draw_buffers', + 'webgl_enable_WEBGL_multi_draw', + 'emscriptenWebGLGet', + 'computeUnpackAlignedImageSize', + 'colorChannelsInGlTextureFormat', + 'emscriptenWebGLGetTexPixelData', + 'emscriptenWebGLGetUniform', + 'webglGetUniformLocation', + 'webglPrepareUniformLocationsBeforeFirstUse', + 'webglGetLeftBracePos', + 'emscriptenWebGLGetVertexAttrib', + '__glGetActiveAttribOrUniform', + 'writeGLArray', + 'registerWebGlEventCallback', + 'runAndAbortIfError', + 'ALLOC_NORMAL', + 'ALLOC_STACK', + 'allocate', + 'writeStringToMemory', + 'writeAsciiToMemory', + 'setErrNo', + 'demangle', + 'stackTrace', + 'getFunctionArgsName', + 'createJsInvokerSignature', + 'createJsInvoker', + 'init_embind', + 'getBasestPointer', + 'registerInheritedInstance', + 'unregisterInheritedInstance', + 'getInheritedInstance', + 'getInheritedInstanceCount', + 'getLiveInheritedInstances', + 'enumReadValueFromPointer', + 'genericPointerToWireType', + 'constNoSmartPtrRawPointerToWireType', + 'nonConstNoSmartPtrRawPointerToWireType', + 'init_RegisteredPointer', + 'RegisteredPointer', + 'RegisteredPointer_fromWireType', + 'runDestructor', + 'releaseClassHandle', + 'detachFinalizer', + 'attachFinalizer', + 'makeClassHandle', + 'init_ClassHandle', + 'ClassHandle', + 'throwInstanceAlreadyDeleted', + 'flushPendingDeletes', + 'setDelayFunction', + 'RegisteredClass', + 'shallowCopyInternalPointer', + 'downcastPointer', + 'upcastPointer', + 'validateThis', + 'char_0', + 'char_9', + 'makeLegalFunctionName', +]; +missingLibrarySymbols.forEach(missingLibrarySymbol) + +var unexportedSymbols = [ + 'run', + 'addOnPreRun', + 'addOnInit', + 'addOnPreMain', + 'addOnExit', + 'addOnPostRun', + 'addRunDependency', + 'removeRunDependency', + 'FS_createFolder', + 'FS_createPath', + 'FS_createLazyFile', + 'FS_createLink', + 'FS_createDevice', + 'FS_readFile', + 'out', + 'err', + 'callMain', + 'abort', + 'wasmMemory', + 'wasmExports', + 'writeStackCookie', + 'checkStackCookie', + 'convertI32PairToI53Checked', + 'stackSave', + 'stackRestore', + 'ptrToString', + 'getHeapMax', + 'growMemory', + 'ENV', + 'MONTH_DAYS_REGULAR', + 'MONTH_DAYS_LEAP', + 'MONTH_DAYS_REGULAR_CUMULATIVE', + 'MONTH_DAYS_LEAP_CUMULATIVE', + 'ERRNO_CODES', + 'ERRNO_MESSAGES', + 'DNS', + 'Protocols', + 'Sockets', + 'timers', + 'warnOnce', + 'readEmAsmArgsArray', + 'jstoi_s', + 'dynCallLegacy', + 'getDynCaller', + 'dynCall', + 'wasmTable', + 'noExitRuntime', + 'freeTableIndexes', + 'functionsInTableMap', + 'setValue', + 'getValue', + 'PATH', + 'PATH_FS', + 'UTF8ArrayToString', + 'UTF8ToString', + 'stringToUTF8Array', + 'stringToUTF8', + 'lengthBytesUTF8', + 'UTF16ToString', + 'stringToUTF16', + 'lengthBytesUTF16', + 'UTF32ToString', + 'stringToUTF32', + 'lengthBytesUTF32', + 'JSEvents', + 'specialHTMLTargets', + 'findCanvasEventTarget', + 'currentFullscreenStrategy', + 'restoreOldWindowedStyle', + 'UNWIND_CACHE', + 'ExitStatus', + 'flush_NO_FILESYSTEM', + 'promiseMap', + 'uncaughtExceptionCount', + 'exceptionLast', + 'exceptionCaught', + 'ExceptionInfo', + 'Browser', + 'getPreloadedImageData__data', + 'wget', + 'SYSCALLS', + 'tempFixedLengthArray', + 'miniTempWebGLFloatBuffers', + 'miniTempWebGLIntBuffers', + 'GL', + 'AL', + 'GLUT', + 'EGL', + 'GLEW', + 'IDBStore', + 'SDL', + 'SDL_gfx', + 'allocateUTF8', + 'allocateUTF8OnStack', + 'InternalError', + 'BindingError', + 'throwInternalError', + 'throwBindingError', + 'registeredTypes', + 'awaitingDependencies', + 'typeDependencies', + 'tupleRegistrations', + 'structRegistrations', + 'sharedRegisterType', + 'whenDependentTypesAreResolved', + 'embind_charCodes', + 'embind_init_charCodes', + 'readLatin1String', + 'getTypeName', + 'getFunctionName', + 'heap32VectorToArray', + 'requireRegisteredType', + 'usesDestructorStack', + 'UnboundTypeError', + 'PureVirtualError', + 'GenericWireTypeSize', + 'EmValType', + 'throwUnboundTypeError', + 'ensureOverloadTable', + 'exposePublicSymbol', + 'replacePublicSymbol', + 'extendError', + 'createNamedFunction', + 'embindRepr', + 'registeredInstances', + 'registeredPointers', + 'registerType', + 'integerReadValueFromPointer', + 'floatReadValueFromPointer', + 'readPointer', + 'runDestructors', + 'craftInvokerFunction', + 'embind__requireFunction', + 'finalizationRegistry', + 'detachFinalizer_deps', + 'deletionQueue', + 'delayFunction', + 'emval_freelist', + 'emval_handles', + 'emval_symbols', + 'init_emval', + 'count_emval_handles', + 'getStringOrSymbol', + 'Emval', + 'emval_get_global', + 'emval_returnValue', + 'emval_lookupTypes', + 'emval_methodCallers', + 'emval_addMethodCaller', + 'reflectConstruct', +]; +unexportedSymbols.forEach(unexportedRuntimeSymbol); + + + +var calledRun; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun) run(); + if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +}; + +function stackCheckInit() { + // This is normally called automatically during __wasm_call_ctors but need to + // get these values before even running any of the ctors so we call it redundantly + // here. + _emscripten_stack_init(); + // TODO(sbc): Move writeStackCookie to native to to avoid this. + writeStackCookie(); +} + +function run() { + + if (runDependencies > 0) { + return; + } + + stackCheckInit(); + + preRun(); + + // a preRun added a dependency, run will be called later + if (runDependencies > 0) { + return; + } + + function doRun() { + // run may have just been called through dependencies being fulfilled just in this very frame, + // or while the async setStatus time below was happening + if (calledRun) return; + calledRun = true; + Module['calledRun'] = true; + + if (ABORT) return; + + initRuntime(); + + readyPromiseResolve(Module); + if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); + + assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'); + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + doRun(); + }, 1); + } else + { + doRun(); + } + checkStackCookie(); +} + +function checkUnflushedContent() { + // Compiler settings do not allow exiting the runtime, so flushing + // the streams is not possible. but in ASSERTIONS mode we check + // if there was something to flush, and if so tell the user they + // should request that the runtime be exitable. + // Normally we would not even include flush() at all, but in ASSERTIONS + // builds we do so just for this check, and here we see if there is any + // content to flush, that is, we check if there would have been + // something a non-ASSERTIONS build would have not seen. + // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0 + // mode (which has its own special function for this; otherwise, all + // the code is inside libc) + var oldOut = out; + var oldErr = err; + var has = false; + out = err = (x) => { + has = true; + } + try { // it doesn't matter if it fails + flush_NO_FILESYSTEM(); + } catch(e) {} + out = oldOut; + err = oldErr; + if (has) { + warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.'); + warnOnce('(this may also be due to not including full filesystem support - try building with -sFORCE_FILESYSTEM)'); + } +} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +run(); + +// end include: postamble.js + + + + return readyPromise +} +); +})(); +export default Module; \ No newline at end of file diff --git a/packages/jxr/dist/codec/dec/jxr_dec.wasm b/packages/jxr/dist/codec/dec/jxr_dec.wasm new file mode 100755 index 0000000..298c335 Binary files /dev/null and b/packages/jxr/dist/codec/dec/jxr_dec.wasm differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr.tar.gz b/packages/jxr/dist/codec/node_modules/jpegxr.tar.gz new file mode 100644 index 0000000..916da4a Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr.tar.gz differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/.extracted b/packages/jxr/dist/codec/node_modules/jpegxr/.extracted new file mode 100644 index 0000000..e69de29 diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/.gitignore b/packages/jxr/dist/codec/node_modules/jpegxr/.gitignore new file mode 100644 index 0000000..c5cad0b --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/.gitignore @@ -0,0 +1,5 @@ +/target +Cargo.lock +.vscode +/wasm/jpegxr.js +*.o diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/Cargo.toml b/packages/jxr/dist/codec/node_modules/jpegxr/Cargo.toml new file mode 100644 index 0000000..7f38f8e --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "jpegxr" +version = "0.3.1" +authors = ["Brooke Vibber "] +edition = "2018" +license = "BSD-3-Clause" +description = "Wrapper for Microsoft's C JPEG XR image codec library" +readme = "readme.md" +homepage = "https://github.com/brion/jpegxr" +repository = "https://github.com/brion/jpegxr.git" +keywords = ["jxr", "jpegxr", "jpeg-xr"] +categories = ["multimedia::images"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +thiserror = "1.0.57" +libc = "0.2.153" + +[build-dependencies] +cc = { version = "1.0.83", features = ["parallel"] } +bindgen = "0.69.4" diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/Makefile b/packages/jxr/dist/codec/node_modules/jpegxr/Makefile new file mode 100644 index 0000000..d3a1455 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/Makefile @@ -0,0 +1,75 @@ +CFLAGS := \ + -O2 \ + -D__ANSI__ \ + -DDISABLE_PERF_MEASUREMENT \ + -Ijxrlib/jxrgluelib \ + -Ijxrlib/common/include \ + -Ijxrlib/image/sys \ + -Wno-constant-conversion \ + -Wno-unused-const-variable \ + -Wno-deprecated-declarations \ + -Wno-comment \ + -Wno-unused-value \ + -Wno-unused-function \ + -Wno-unknown-pragmas \ + -Wno-extra-tokens \ + -Wno-missing-field-initializers \ + -Wno-shift-negative-value \ + -Wno-dangling-else \ + -Wno-sign-compare + +LINK_FLAGS := \ + -s SUPPORT_BIG_ENDIAN=1 \ + -s MODULARIZE=1 \ + -s EXPORT_NAME=jpegxr \ + -s SINGLE_FILE=1 \ + --no-entry \ + --post-js=wasm/wasm_api.js \ + -s EXPORTED_FUNCTIONS='["_malloc","_free"]' \ + -s ALLOW_MEMORY_GROWTH=1 + + +SOURCES := \ + jxrlib/image/sys/adapthuff.c \ + jxrlib/image/sys/image.c \ + jxrlib/image/sys/strcodec.c \ + jxrlib/image/sys/strPredQuant.c \ + jxrlib/image/sys/strTransform.c \ + jxrlib/image/sys/perfTimerANSI.c \ + jxrlib/image/decode/decode.c \ + jxrlib/image/decode/postprocess.c \ + jxrlib/image/decode/segdec.c \ + jxrlib/image/decode/strdec.c \ + jxrlib/image/decode/strInvTransform.c \ + jxrlib/image/decode/strPredQuantDec.c \ + jxrlib/image/decode/JXRTranscode.c \ + jxrlib/image/encode/encode.c \ + jxrlib/image/encode/segenc.c \ + jxrlib/image/encode/strenc.c \ + jxrlib/image/encode/strFwdTransform.c \ + jxrlib/image/encode/strPredQuantEnc.c \ + jxrlib/jxrgluelib/JXRGlue.c \ + jxrlib/jxrgluelib/JXRGlueJxr.c \ + jxrlib/jxrgluelib/JXRGluePFC.c \ + jxrlib/jxrgluelib/JXRMeta.c \ + wasm/wasm_api.c + +OBJECTS := ${SOURCES:.c=.o} + +OUTPUT := wasm/jpegxr.js + +.PHONY: all clean + +all: ${OUTPUT} ${DIS} + +clean: + rm -f ${OBJECTS} ${OUTPUT} + +test: ${OUTPUT} + node wasm/test.js + +${OUTPUT} : ${OBJECTS} Makefile + emcc ${CFLAGS} ${LINK_FLAGS} -o ${OUTPUT} ${OBJECTS} + +%.o : %.c Makefile + emcc ${CFLAGS} -o $@ -c $< diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/build.rs b/packages/jxr/dist/codec/node_modules/jpegxr/build.rs new file mode 100644 index 0000000..264d3fe --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/build.rs @@ -0,0 +1,86 @@ +use std::env; +use std::path::PathBuf; + +fn main() { + let src = &[ + // SRC_SYS + "jxrlib/image/sys/adapthuff.c", + "jxrlib/image/sys/image.c", + "jxrlib/image/sys/strcodec.c", + "jxrlib/image/sys/strPredQuant.c", + "jxrlib/image/sys/strTransform.c", + "jxrlib/image/sys/perfTimerANSI.c", + // SRC_DEC + "jxrlib/image/decode/decode.c", + "jxrlib/image/decode/postprocess.c", + "jxrlib/image/decode/segdec.c", + "jxrlib/image/decode/strdec.c", + "jxrlib/image/decode/strInvTransform.c", + "jxrlib/image/decode/strPredQuantDec.c", + "jxrlib/image/decode/JXRTranscode.c", + // SRC_ENC + "jxrlib/image/encode/encode.c", + "jxrlib/image/encode/segenc.c", + "jxrlib/image/encode/strenc.c", + "jxrlib/image/encode/strFwdTransform.c", + "jxrlib/image/encode/strPredQuantEnc.c", + // glue lib + "jxrlib/jxrgluelib/JXRGlue.c", + "jxrlib/jxrgluelib/JXRGlueJxr.c", + "jxrlib/jxrgluelib/JXRGluePFC.c", + "jxrlib/jxrgluelib/JXRMeta.c", + ]; + cc::Build::new() + .files(src) + .include("jxrlib") + .include("jxrlib/common/include") + .include("jxrlib/image/sys") + .include("jxrlib/jxrgluelib") + .define("__ANSI__", None) + .define("DISABLE_PERF_MEASUREMENT", None) + // quiet the build on mac with clang + .flag_if_supported("-Wno-constant-conversion") + .flag_if_supported("-Wno-unused-const-variable") + .flag_if_supported("-Wno-deprecated-declarations") + .flag_if_supported("-Wno-comment") + .flag_if_supported("-Wno-unused-value") + .flag_if_supported("-Wno-unused-function") + .flag_if_supported("-Wno-unknown-pragmas") + .flag_if_supported("-Wno-extra-tokens") + .flag_if_supported("-Wno-missing-field-initializers") + .flag_if_supported("-Wno-shift-negative-value") + .flag_if_supported("-Wno-dangling-else") + .flag_if_supported("-Wno-sign-compare") + // quiet the build on linux with gcc + .flag_if_supported("-Wno-strict-aliasing") + .flag_if_supported("-Wno-implicit-fallthrough") + .flag_if_supported("-Wno-old-style-declaration") + .flag_if_supported("-Wno-endif-labels") + .flag_if_supported("-Wno-parentheses") + .flag_if_supported("-Wno-misleading-indentation") + .flag_if_supported("-Wno-unused-but-set-variable") + .opt_level(2) + .compile("jpegxr"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let clang_args = &[ + "-D__ANSI__", + "-DDISABLE_PERF_MEASUREMENT", + "-Ijxrlib/jxrgluelib", + "-Ijxrlib/common/include", + "-Ijxrlib/image/sys", + ]; + bindgen::Builder::default() + .header("jxrlib/jxrgluelib/JXRGlue.h") + .allowlist_function("^(WMP|PK|PixelFormatLookup|GetPixelFormatFromHash|GetImageEncodeIID|GetImageDecodeIID|FreeDescMetadata).*") + .allowlist_var("^(WMP|PK|LOOKUP|GUID_PK|IID).*") + .allowlist_type("^(WMP|PK|ERR|BITDEPTH|BD_|BITDEPTH_BITS|COLORFORMAT).*") + .clang_args(clang_args) + .derive_eq(true) + .size_t_is_usize(true) + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .generate() + .expect("Error building libjpegxr bindings") + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/guiddef.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/guiddef.h new file mode 100644 index 0000000..b566c68 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/guiddef.h @@ -0,0 +1,231 @@ +//+--------------------------------------------------------------------------- +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// File: guiddef.h +// +// Contents: GUID definition +// +//---------------------------------------------------------------------------- + +#ifndef GUID_DEFINED +#define GUID_DEFINED +#if defined(__midl) +typedef struct { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + byte Data4[ 8 ]; +} GUID; +#else +typedef struct _GUID { +#if defined(_WINDOWS_) || !__LP64__ + unsigned long Data1; +#else + unsigned int Data1; +#endif + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; +} GUID; +#endif +#endif + +#ifndef FAR +#if defined(_WIN32) || defined(__ANSI__) +#define FAR +#else +//#define FAR _far +#define FAR +#endif +#endif + +#ifndef DECLSPEC_SELECTANY +#if (_MSC_VER >= 1100) +#define DECLSPEC_SELECTANY __declspec(selectany) +#else +#define DECLSPEC_SELECTANY +#endif +#endif + +#ifndef EXTERN_C +#ifdef __cplusplus +#define EXTERN_C extern "C" +#else +#define EXTERN_C extern +#endif +#endif + +#ifdef DEFINE_GUID +#undef DEFINE_GUID +#endif + +#ifdef INITGUID +#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + const GUID DECLSPEC_SELECTANY name \ + = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else +#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + EXTERN_C const GUID FAR name +#endif // INITGUID + +#define DEFINE_OLEGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46) + +#ifndef _GUIDDEF_H_ +#define _GUIDDEF_H_ + +#ifndef __LPGUID_DEFINED__ +#define __LPGUID_DEFINED__ +typedef GUID *LPGUID; +#endif + +#ifndef __LPCGUID_DEFINED__ +#define __LPCGUID_DEFINED__ +typedef const GUID *LPCGUID; +#endif + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef GUID IID; +typedef IID *LPIID; +#define IID_NULL GUID_NULL +#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2) +typedef GUID CLSID; +typedef CLSID *LPCLSID; +#define CLSID_NULL GUID_NULL +#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2) +typedef GUID FMTID; +typedef FMTID *LPFMTID; +#define FMTID_NULL GUID_NULL +#define IsEqualFMTID(rfmtid1, rfmtid2) IsEqualGUID(rfmtid1, rfmtid2) + +#ifdef __midl_proxy +#define __MIDL_CONST +#else +#define __MIDL_CONST const +#endif + +#ifndef _REFGUID_DEFINED +#define _REFGUID_DEFINED +#ifdef __cplusplus +#define REFGUID const GUID & +#else +#define REFGUID const GUID * __MIDL_CONST +#endif +#endif + +#ifndef _REFIID_DEFINED +#define _REFIID_DEFINED +#ifdef __cplusplus +#define REFIID const IID & +#else +#define REFIID const IID * __MIDL_CONST +#endif +#endif + +#ifndef _REFCLSID_DEFINED +#define _REFCLSID_DEFINED +#ifdef __cplusplus +#define REFCLSID const IID & +#else +#define REFCLSID const IID * __MIDL_CONST +#endif +#endif + +#ifndef _REFFMTID_DEFINED +#define _REFFMTID_DEFINED +#ifdef __cplusplus +#define REFFMTID const IID & +#else +#define REFFMTID const IID * __MIDL_CONST +#endif +#endif + +#endif // !__IID_DEFINED__ + +#if !defined (__midl) +#if !defined (_SYS_GUID_OPERATORS_) +#define _SYS_GUID_OPERATORS_ +#include + +// Faster (but makes code fatter) inline version...use sparingly +#ifdef __cplusplus +__inline int InlineIsEqualGUID(REFGUID rguid1, REFGUID rguid2) +{ + return ( + ((unsigned long *) &rguid1)[0] == ((unsigned long *) &rguid2)[0] && + ((unsigned long *) &rguid1)[1] == ((unsigned long *) &rguid2)[1] && + ((unsigned long *) &rguid1)[2] == ((unsigned long *) &rguid2)[2] && + ((unsigned long *) &rguid1)[3] == ((unsigned long *) &rguid2)[3]); +} + +__inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2) +{ + return !memcmp(&rguid1, &rguid2, sizeof(GUID)); +} + +#else // ! __cplusplus + +#define InlineIsEqualGUID(rguid1, rguid2) \ + (((unsigned long *) rguid1)[0] == ((unsigned long *) rguid2)[0] && \ + ((unsigned long *) rguid1)[1] == ((unsigned long *) rguid2)[1] && \ + ((unsigned long *) rguid1)[2] == ((unsigned long *) rguid2)[2] && \ + ((unsigned long *) rguid1)[3] == ((unsigned long *) rguid2)[3]) + +#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID))) + +#endif // __cplusplus + +#ifdef __INLINE_ISEQUAL_GUID +#undef IsEqualGUID +#define IsEqualGUID(rguid1, rguid2) InlineIsEqualGUID(rguid1, rguid2) +#endif + +// Same type, different name + +#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2) +#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2) + + +#if !defined _SYS_GUID_OPERATOR_EQ_ && !defined _NO_SYS_GUID_OPERATOR_EQ_ +#define _SYS_GUID_OPERATOR_EQ_ +// A couple of C++ helpers + +#ifdef __cplusplus +__inline int operator==(REFGUID guidOne, REFGUID guidOther) +{ + return IsEqualGUID(guidOne,guidOther); +} + +__inline int operator!=(REFGUID guidOne, REFGUID guidOther) +{ + return !(guidOne == guidOther); +} +#endif +#endif // _SYS_GUID_OPERATOR_EQ_ +#endif // _SYS_GUID_OPERATORS_ +#endif // __midl +#endif // _GUIDDEF_H_ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmsal.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmsal.h new file mode 100644 index 0000000..44d00ec --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmsal.h @@ -0,0 +1,757 @@ +/*** +*sal.h - markers for documenting the semantics of APIs +* +* Copyright © Microsoft Corp. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* • Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* • Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*Purpose: +* sal.h provides a set of annotations to describe how a function uses its +* parameters - the assumptions it makes about them, and the guarantees it makes +* upon finishing. +* +* [Public] +* +****/ + +/* + ------------------------------------------------------------------------------- + Introduction + + sal.h provides a set of annotations to describe how a function uses its + parameters - the assumptions it makes about them, and the guarantees it makes + upon finishing. + + Annotations may be placed before either a function parameter's type or its return + type, and describe the function's behavior regarding the parameter or return value. + There are two classes of annotations: buffer annotations and advanced annotations. + Buffer annotations describe how functions use their pointer parameters, and + advanced annotations either describe complex/unusual buffer behavior, or provide + additional information about a parameter that is not otherwise expressible. + + ------------------------------------------------------------------------------- + Buffer Annotations + + The most important annotations in sal.h provide a consistent way to annotate + buffer parameters or return values for a function. Each of these annotations describes + a single buffer (which could be a string, a fixed-length or variable-length array, + or just a pointer) that the function interacts with: where it is, how large it is, + how much is initialized, and what the function does with it. + + The appropriate macro for a given buffer can be constructed using the table below. + Just pick the appropriate values from each category, and combine them together + with a leading underscore. Some combinations of values do not make sense as buffer + annotations. Only meaningful annotations can be added to your code; for a list of + these, see the buffer annotation definitions section. + + Only a single buffer annotation should be used for each parameter. + + |------------|------------|---------|--------|----------|----------|---------------| + | Level | Usage | Size | Output | NullTerm | Optional | Parameters | + |------------|------------|---------|--------|----------|----------|---------------| + | <> | <> | <> | <> | _z | <> | <> | + | _deref | _in | _ecount | _full | _nz | _opt | (size) | + | _deref_opt | _out | _bcount | _part | | | (size,length) | + | | _inout | | | | | | + | | | | | | | | + |------------|------------|---------|--------|----------|----------|---------------| + + Level: Describes the buffer pointer's level of indirection from the parameter or + return value 'p'. + + <> : p is the buffer pointer. + _deref : *p is the buffer pointer. p must not be NULL. + _deref_opt : *p may be the buffer pointer. p may be NULL, in which case the rest of + the annotation is ignored. + + Usage: Describes how the function uses the buffer. + + <> : The buffer is not accessed. If used on the return value or with _deref, the + function will provide the buffer, and it will be uninitialized at exit. + Otherwise, the caller must provide the buffer. This should only be used + for alloc and free functions. + _in : The function will only read from the buffer. The caller must provide the + buffer and initialize it. Cannot be used with _deref. + _out : The function will only write to the buffer. If used on the return value or + with _deref, the function will provide the buffer and initialize it. + Otherwise, the caller must provide the buffer, and the function will + initialize it. + _inout : The function may freely read from and write to the buffer. The caller must + provide the buffer and initialize it. If used with _deref, the buffer may + be reallocated by the function. + + Size: Describes the total size of the buffer. This may be less than the space actually + allocated for the buffer, in which case it describes the accessible amount. + + <> : No buffer size is given. If the type specifies the buffer size (such as + with LPSTR and LPWSTR), that amount is used. Otherwise, the buffer is one + element long. Must be used with _in, _out, or _inout. + _ecount : The buffer size is an explicit element count. + _bcount : The buffer size is an explicit byte count. + + Output: Describes how much of the buffer will be initialized by the function. For + _inout buffers, this also describes how much is initialized at entry. Omit this + category for _in buffers; they must be fully initialized by the caller. + + <> : The type specifies how much is initialized. For instance, a function initializing + an LPWSTR must NULL-terminate the string. + _full : The function initializes the entire buffer. + _part : The function initializes part of the buffer, and explicitly indicates how much. + + NullTerm: States if the present of a '\0' marks the end of valid elements in the buffer. + _z : A '\0' indicated the end of the buffer + _nz : The buffer may not be null terminated and a '\0' does not indicate the end of the + buffer. + Optional: Describes if the buffer itself is optional. + + <> : The pointer to the buffer must not be NULL. + _opt : The pointer to the buffer might be NULL. It will be checked before being dereferenced. + + Parameters: Gives explicit counts for the size and length of the buffer. + + <> : There is no explicit count. Use when neither _ecount nor _bcount is used. + (size) : Only the buffer's total size is given. Use with _ecount or _bcount but not _part. + (size,length) : The buffer's total size and initialized length are given. Use with _ecount_part + and _bcount_part. + + ------------------------------------------------------------------------------- + Buffer Annotation Examples + + LWSTDAPI_(BOOL) StrToIntExA( + LPCSTR pszString, -- No annotation required, const implies __in. + DWORD dwFlags, + __out int *piRet -- A pointer whose dereference will be filled in. + ); + + void MyPaintingFunction( + __in HWND hwndControl, -- An initialized read-only parameter. + __in_opt HDC hdcOptional, -- An initialized read-only parameter that might be NULL. + __inout IPropertyStore *ppsStore -- An initialized parameter that may be freely used + -- and modified. + ); + + LWSTDAPI_(BOOL) PathCompactPathExA( + __out_ecount(cchMax) LPSTR pszOut, -- A string buffer with cch elements that will + -- be NULL terminated on exit. + LPCSTR pszSrc, -- No annotation required, const implies __in. + UINT cchMax, + DWORD dwFlags + ); + + HRESULT SHLocalAllocBytes( + size_t cb, + __deref_bcount(cb) T **ppv -- A pointer whose dereference will be set to an + -- uninitialized buffer with cb bytes. + ); + + __inout_bcount_full(cb) : A buffer with cb elements that is fully initialized at + entry and exit, and may be written to by this function. + + __out_ecount_part(count, *countOut) : A buffer with count elements that will be + partially initialized by this function. The function indicates how much it + initialized by setting *countOut. + + ------------------------------------------------------------------------------- + Advanced Annotations + + Advanced annotations describe behavior that is not expressible with the regular + buffer macros. These may be used either to annotate buffer parameters that involve + complex or conditional behavior, or to enrich existing annotations with additional + information. + + __success(expr) f : + indicates whether function f succeeded or not. If is true at exit, + all the function's guarantees (as given by other annotations) must hold. If + is false at exit, the caller should not expect any of the function's guarantees + to hold. If not used, the function must always satisfy its guarantees. Added + automatically to functions that indicate success in standard ways, such as by + returning an HRESULT. + + __nullterminated p : + Pointer p is a buffer that may be read or written up to and including the first + NULL character or pointer. May be used on typedefs, which marks valid (properly + initialized) instances of that type as being NULL-terminated. + + __nullnullterminated p : + Pointer p is a buffer that may be read or written up to and including the first + sequence of two NULL characters or pointers. May be used on typedefs, which marks + valid instances of that type as being double-NULL terminated. + + __reserved v : + Value v must be 0/NULL, reserved for future use. + + __checkReturn v : + Return value v must not be ignored by callers of this function. + + __typefix(ctype) v : + Value v should be treated as an instance of ctype, rather than its declared type. + + __override f : + Specify C#-style 'override' behaviour for overriding virtual methods. + + __callback f : + Function f can be used as a function pointer. + + __format_string p : + Pointer p is a string that contains % markers in the style of printf. + + __blocksOn(resource) f : + Function f blocks on the resource 'resource'. + + __fallthrough : + Annotates switch statement labels where fall-through is desired, to distinguish + from forgotten break statements. + + ------------------------------------------------------------------------------- + Advanced Annotation Examples + + __success(return == TRUE) LWSTDAPI_(BOOL) + PathCanonicalizeA(__out_ecount(MAX_PATH) LPSTR pszBuf, LPCSTR pszPath) : + pszBuf is only guaranteed to be NULL-terminated when TRUE is returned. + + typedef __nullterminated WCHAR* LPWSTR : Initialized LPWSTRs are NULL-terminated strings. + + __out_ecount(cch) __typefix(LPWSTR) void *psz : psz is a buffer parameter which will be + a NULL-terminated WCHAR string at exit, and which initially contains cch WCHARs. + + ------------------------------------------------------------------------------- +*/ + +#pragma once +#ifndef __specstrings +#define __specstrings + +#ifdef __cplusplus +#ifndef __nothrow +# define __nothrow __declspec(nothrow) +#endif +extern "C" { +#else +#ifndef __nothrow +# define __nothrow +#endif +#endif /* #ifdef __cplusplus */ + +/* + ------------------------------------------------------------------------------- + Helper Macro Definitions + + These express behavior common to many of the high-level annotations. + DO NOT USE THESE IN YOUR CODE. + ------------------------------------------------------------------------------- +*/ + +/* +The helper annotations are only understood by the compiler version used by various +defect detection tools. When the regular compiler is running, they are defined into +nothing, and do not affect the compiled code. +*/ + +#if !defined(__midl) && defined(_PREFAST_) + + /* + In the primitive __declspec("SAL_*") annotations "SAL" stands for Standard + Annotation Language. These __declspec("SAL_*") annotations are the + primitives the compiler understands and all high-level SpecString MACROs + will decompose into these primivates. + */ + + #define SPECSTRINGIZE( x ) #x + + /* + __null p + __notnull p + __maybenull p + + Annotates a pointer p. States that pointer p is null. Commonly used + in the negated form __notnull or the possibly null form __maybenull. + */ + +// #define __null __declspec("SAL_null") + #define __notnull __declspec("SAL_notnull") + #define __maybenull __declspec("SAL_maybenull") + + /* + __readonly l + __notreadonly l + __mabyereadonly l + + Annotates a location l. States that location l is not modified after + this point. If the annotation is placed on the precondition state of + a function, the restriction only applies until the postcondition state + of the function. __maybereadonly states that the annotated location + may be modified, whereas __notreadonly states that a location must be + modified. + */ + + #define __readonly __declspec("SAL_readonly") + #define __notreadonly __declspec("SAL_notreadonly") + #define __maybereadonly __declspec("SAL_maybereadonly") + + /* + __valid v + __notvalid v + __maybevalid v + + Annotates any value v. States that the value satisfies all properties of + valid values of its type. For example, for a string buffer, valid means + that the buffer pointer is either NULL or points to a NULL-terminated string. + */ + + #define __valid __declspec("SAL_valid") + #define __notvalid __declspec("SAL_notvalid") + #define __maybevalid __declspec("SAL_maybevalid") + + /* + __readableTo(extent) p + + Annotates a buffer pointer p. If the buffer can be read, extent describes + how much of the buffer is readable. For a reader of the buffer, this is + an explicit permission to read up to that amount, rather than a restriction to + read only up to it. + */ + + #define __readableTo(extent) __declspec("SAL_readableTo("SPECSTRINGIZE(extent)")") + + /* + + __elem_readableTo(size) + + Annotates a buffer pointer p as being readable to size elements. + */ + + #define __elem_readableTo(size) __declspec("SAL_readableTo(elementCount("SPECSTRINGIZE(size)"))") + + /* + __byte_readableTo(size) + + Annotates a buffer pointer p as being readable to size bytes. + */ + #define __byte_readableTo(size) __declspec("SAL_readableTo(byteCount("SPECSTRINGIZE(size)"))") + + /* + __writableTo(extent) p + + Annotates a buffer pointer p. If the buffer can be modified, extent + describes how much of the buffer is writable (usually the allocation + size). For a writer of the buffer, this is an explicit permission to + write up to that amount, rather than a restriction to write only up to it. + */ + #define __writableTo(size) __declspec("SAL_writableTo("SPECSTRINGIZE(size)")") + + /* + __elem_writableTo(size) + + Annotates a buffer pointer p as being writable to size elements. + */ + #define __elem_writableTo(size) __declspec("SAL_writableTo(elementCount("SPECSTRINGIZE(size)"))") + + /* + __byte_writableTo(size) + + Annotates a buffer pointer p as being writable to size bytes. + */ + #define __byte_writableTo(size) __declspec("SAL_writableTo(byteCount("SPECSTRINGIZE(size)"))") + + /* + __deref p + + Annotates a pointer p. The next annotation applies one dereference down + in the type. If readableTo(p, size) then the next annotation applies to + all elements *(p+i) for which i satisfies the size. If p is a pointer + to a struct, the next annotation applies to all fields of the struct. + */ + #define __deref __declspec("SAL_deref") + + /* + __pre __next_annotation + + The next annotation applies in the precondition state + */ + #define __pre __declspec("SAL_pre") + + /* + __post __next_annotation + + The next annotation applies in the postcondition state + */ + #define __post __declspec("SAL_post") + + /* + __precond() + + When is true, the next annotation applies in the precondition state + (currently not enabled) + */ + #define __precond(expr) __pre + + /* + __postcond() + + When is true, the next annotation applies in the postcondition state + (currently not enabled) + */ + #define __postcond(expr) __post + + /* + __exceptthat + + Given a set of annotations Q containing __exceptthat maybeP, the effect of + the except clause is to erase any P or notP annotations (explicit or + implied) within Q at the same level of dereferencing that the except + clause appears, and to replace it with maybeP. + + Example 1: __valid __exceptthat __maybenull on a pointer p means that the + pointer may be null, and is otherwise valid, thus overriding + the implicit notnull annotation implied by __valid on + pointers. + + Example 2: __valid __deref __exceptthat __maybenull on an int **p means + that p is not null (implied by valid), but the elements + pointed to by p could be null, and are otherwise valid. + */ + #define __exceptthat __declspec("SAL_except") + #define __execeptthat __exceptthat + + /* + _refparam + + Added to all out parameter macros to indicate that they are all reference + parameters. + */ + #define __refparam __deref __notreadonly + + /* + __inner_* + + Helper macros that directly correspond to certain high-level annotations. + + */ + + /* + Macros to classify the entrypoints and indicate their category. + + Pre-defined control point categories include: RPC, LPC, DeviceDriver, UserToKernel, ISAPI, COM. + + */ + #define __inner_control_entrypoint(category) __declspec("SAL_entrypoint(controlEntry, "SPECSTRINGIZE(category)")") + + /* + Pre-defined data entry point categories include: Registry, File, Network. + */ + #define __inner_data_entrypoint(category) __declspec("SAL_entrypoint(dataEntry, "SPECSTRINGIZE(category)")") + + #define __inner_success(expr) __declspec("SAL_success("SPECSTRINGIZE(expr)")") + #define __inner_checkReturn __declspec("SAL_checkReturn") + #define __inner_typefix(ctype) __declspec("SAL_typefix("SPECSTRINGIZE(ctype)")") + #define __inner_override __declspec("__override") + #define __inner_callback __declspec("__callback") + #define __inner_blocksOn(resource) __declspec("SAL_blocksOn("SPECSTRINGIZE(resource)")") + #define __inner_fallthrough_dec __inline __nothrow void __FallThrough() {} + #define __inner_fallthrough __FallThrough(); + +#else +// This conflicts with gcc definition of __null. +// #define __null + #define __notnull + #define __maybenull + #define __readonly + #define __notreadonly + #define __maybereadonly + #define __valid + #define __notvalid + #define __maybevalid + #define __readableTo(extent) + #define __elem_readableTo(size) + #define __byte_readableTo(size) + #define __writableTo(size) + #define __elem_writableTo(size) + #define __byte_writableTo(size) + #define __deref + #define __pre + #define __post + #define __precond(expr) + #define __postcond(expr) + #define __exceptthat + #define __execeptthat + #define __inner_success(expr) + #define __inner_checkReturn + #define __inner_typefix(ctype) + #define __inner_override + #define __inner_callback + #define __inner_blocksOn(resource) + #define __inner_fallthrough_dec + #define __inner_fallthrough + #define __refparam + #define __inner_control_entrypoint(category) + #define __inner_data_entrypoint(category) +#endif /* #if !defined(__midl) && defined(_PREFAST_) */ + +/* +------------------------------------------------------------------------------- +Buffer Annotation Definitions + +Any of these may be used to directly annotate functions, but only one should +be used for each parameter. To determine which annotation to use for a given +buffer, use the table in the buffer annotations section. +------------------------------------------------------------------------------- +*/ + +#define __ecount(size) __notnull __elem_writableTo(size) +#define __bcount(size) __notnull __byte_writableTo(size) +//#define __in __pre __valid __pre __deref __readonly +#define __in_win __pre __valid __pre __deref __readonly + +#define __in_ecount(size) __in_win __pre __elem_readableTo(size) +#define __in_bcount(size) __in_win __pre __byte_readableTo(size) +#define __in_z __in_win __pre __nullterminated +#define __in_ecount_z(size) __in_ecount(size) __pre __nullterminated +#define __in_bcount_z(size) __in_bcount(size) __pre __nullterminated +#define __in_nz __in_win +#define __in_ecount_nz(size) __in_ecount(size) +#define __in_bcount_nz(size) __in_bcount(size) + +//#define __out __ecount(1) __post __valid __refparam +#define __out_win __ecount(1) __post __valid __refparam + +#define __out_ecount(size) __ecount(size) __post __valid __refparam +#define __out_bcount(size) __bcount(size) __post __valid __refparam +#define __out_ecount_part(size,length) __out_ecount(size) __post __elem_readableTo(length) +#define __out_bcount_part(size,length) __out_bcount(size) __post __byte_readableTo(length) +#define __out_ecount_full(size) __out_ecount_part(size,size) +#define __out_bcount_full(size) __out_bcount_part(size,size) +#define __out_z __post __valid __refparam __post __nullterminated +#define __out_z_opt __post __valid __refparam __post __nullterminated __exceptthat __maybenull +#define __out_ecount_z(size) __ecount(size) __post __valid __refparam __post __nullterminated +#define __out_bcount_z(size) __bcount(size) __post __valid __refparam __post __nullterminated +#define __out_ecount_part_z(size,length) __out_ecount_part(size,length) __post __nullterminated +#define __out_bcount_part_z(size,length) __out_bcount_part(size,length) __post __nullterminated +#define __out_ecount_full_z(size) __out_ecount_full(size) __post __nullterminated +#define __out_bcount_full_z(size) __out_bcount_full(size) __post __nullterminated +#define __out_nz __post __valid __refparam __post +#define __out_nz_opt __post __valid __refparam __post __exceptthat __maybenull +#define __out_ecount_nz(size) __ecount(size) __post __valid __refparam +#define __out_bcount_nz(size) __bcount(size) __post __valid __refparam +#define __inout __pre __valid __post __valid __refparam +#define __inout_ecount(size) __out_ecount(size) __pre __valid +#define __inout_bcount(size) __out_bcount(size) __pre __valid +#define __inout_ecount_part(size,length) __out_ecount_part(size,length) __pre __valid __pre __elem_readableTo(length) +#define __inout_bcount_part(size,length) __out_bcount_part(size,length) __pre __valid __pre __byte_readableTo(length) +#define __inout_ecount_full(size) __inout_ecount_part(size,size) +#define __inout_bcount_full(size) __inout_bcount_part(size,size) +#define __inout_z __inout __pre __nullterminated __post __nullterminated +#define __inout_ecount_z(size) __inout_ecount(size) __pre __nullterminated __post __nullterminated +#define __inout_bcount_z(size) __inout_bcount(size) __pre __nullterminated __post __nullterminated +#define __inout_nz __inout +#define __inout_ecount_nz(size) __inout_ecount(size) +#define __inout_bcount_nz(size) __inout_bcount(size) +#define __ecount_opt(size) __ecount(size) __exceptthat __maybenull +#define __bcount_opt(size) __bcount(size) __exceptthat __maybenull +#define __in_opt __in_win __exceptthat __maybenull +#define __in_ecount_opt(size) __in_ecount(size) __exceptthat __maybenull +#define __in_bcount_opt(size) __in_bcount(size) __exceptthat __maybenull +#define __in_z_opt __in_opt __pre __nullterminated +#define __in_ecount_z_opt(size) __in_ecount_opt(size) __pre __nullterminated +#define __in_bcount_z_opt(size) __in_bcount_opt(size) __pre __nullterminated +#define __in_nz_opt __in_opt +#define __in_ecount_nz_opt(size) __in_ecount_opt(size) +#define __in_bcount_nz_opt(size) __in_bcount_opt(size) +#define __out_opt __out_win __exceptthat __maybenull +#define __out_ecount_opt(size) __out_ecount(size) __exceptthat __maybenull +#define __out_bcount_opt(size) __out_bcount(size) __exceptthat __maybenull +#define __out_ecount_part_opt(size,length) __out_ecount_part(size,length) __exceptthat __maybenull +#define __out_bcount_part_opt(size,length) __out_bcount_part(size,length) __exceptthat __maybenull +#define __out_ecount_full_opt(size) __out_ecount_full(size) __exceptthat __maybenull +#define __out_bcount_full_opt(size) __out_bcount_full(size) __exceptthat __maybenull +#define __out_ecount_z_opt(size) __out_ecount_opt(size) __post __nullterminated +#define __out_bcount_z_opt(size) __out_bcount_opt(size) __post __nullterminated +#define __out_ecount_part_z_opt(size,length) __out_ecount_part_opt(size,length) __post __nullterminated +#define __out_bcount_part_z_opt(size,length) __out_bcount_part_opt(size,length) __post __nullterminated +#define __out_ecount_full_z_opt(size) __out_ecount_full_opt(size) __post __nullterminated +#define __out_bcount_full_z_opt(size) __out_bcount_full_opt(size) __post __nullterminated +#define __out_ecount_nz_opt(size) __out_ecount_opt(size) __post __nullterminated +#define __out_bcount_nz_opt(size) __out_bcount_opt(size) __post __nullterminated +#define __inout_opt __inout __exceptthat __maybenull +#define __inout_ecount_opt(size) __inout_ecount(size) __exceptthat __maybenull +#define __inout_bcount_opt(size) __inout_bcount(size) __exceptthat __maybenull +#define __inout_ecount_part_opt(size,length) __inout_ecount_part(size,length) __exceptthat __maybenull +#define __inout_bcount_part_opt(size,length) __inout_bcount_part(size,length) __exceptthat __maybenull +#define __inout_ecount_full_opt(size) __inout_ecount_full(size) __exceptthat __maybenull +#define __inout_bcount_full_opt(size) __inout_bcount_full(size) __exceptthat __maybenull +#define __inout_z_opt __inout_opt __pre __nullterminated __post __nullterminated +#define __inout_ecount_z_opt(size) __inout_ecount_opt(size) __pre __nullterminated __post __nullterminated +#define __inout_ecount_z_opt(size) __inout_ecount_opt(size) __pre __nullterminated __post __nullterminated +#define __inout_bcount_z_opt(size) __inout_bcount_opt(size) +#define __inout_nz_opt __inout_opt +#define __inout_ecount_nz_opt(size) __inout_ecount_opt(size) +#define __inout_bcount_nz_opt(size) __inout_bcount_opt(size) +#define __deref_ecount(size) __ecount(1) __post __elem_readableTo(1) __post __deref __notnull __post __deref __elem_writableTo(size) +#define __deref_bcount(size) __ecount(1) __post __elem_readableTo(1) __post __deref __notnull __post __deref __byte_writableTo(size) +#define __deref_out __deref_ecount(1) __post __deref __valid __refparam +#define __deref_out_ecount(size) __deref_ecount(size) __post __deref __valid __refparam +#define __deref_out_bcount(size) __deref_bcount(size) __post __deref __valid __refparam +#define __deref_out_ecount_part(size,length) __deref_out_ecount(size) __post __deref __elem_readableTo(length) +#define __deref_out_bcount_part(size,length) __deref_out_bcount(size) __post __deref __byte_readableTo(length) +#define __deref_out_ecount_full(size) __deref_out_ecount_part(size,size) +#define __deref_out_bcount_full(size) __deref_out_bcount_part(size,size) +#define __deref_out_z __post __deref __valid __refparam __post __deref __nullterminated +#define __deref_out_ecount_z(size) __deref_out_ecount(size) __post __deref __nullterminated +#define __deref_out_bcount_z(size) __deref_out_ecount(size) __post __deref __nullterminated +#define __deref_out_nz __deref_out +#define __deref_out_ecount_nz(size) __deref_out_ecount(size) +#define __deref_out_bcount_nz(size) __deref_out_ecount(size) +#define __deref_inout __notnull __elem_readableTo(1) __pre __deref __valid __post __deref __valid __refparam +#define __deref_inout_z __deref_inout __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_inout_ecount(size) __deref_inout __pre __deref __elem_writableTo(size) __post __deref __elem_writableTo(size) +#define __deref_inout_bcount(size) __deref_inout __pre __deref __byte_writableTo(size) __post __deref __byte_writableTo(size) +#define __deref_inout_ecount_part(size,length) __deref_inout_ecount(size) __pre __deref __elem_readableTo(length) __post __deref __elem_readableTo(length) +#define __deref_inout_bcount_part(size,length) __deref_inout_bcount(size) __pre __deref __byte_readableTo(length) __post __deref __byte_readableTo(length) +#define __deref_inout_ecount_full(size) __deref_inout_ecount_part(size,size) +#define __deref_inout_bcount_full(size) __deref_inout_bcount_part(size,size) +#define __deref_inout_z __deref_inout __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_inout_ecount_z(size) __deref_inout_ecount(size) __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_inout_bcount_z(size) __deref_inout_ecount(size) __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_inout_nz __deref_inout +#define __deref_inout_ecount_nz(size) __deref_inout_ecount(size) +#define __deref_inout_bcount_nz(size) __deref_inout_ecount(size) +#define __deref_ecount_opt(size) __deref_ecount(size) __post __deref __exceptthat __maybenull +#define __deref_bcount_opt(size) __deref_bcount(size) __post __deref __exceptthat __maybenull +#define __deref_out_opt __deref_out __post __deref __exceptthat __maybenull +#define __deref_out_ecount_opt(size) __deref_out_ecount(size) __post __deref __exceptthat __maybenull +#define __deref_out_bcount_opt(size) __deref_out_bcount(size) __post __deref __exceptthat __maybenull +#define __deref_out_ecount_part_opt(size,length) __deref_out_ecount_part(size,length) __post __deref __exceptthat __maybenull +#define __deref_out_bcount_part_opt(size,length) __deref_out_bcount_part(size,length) __post __deref __exceptthat __maybenull +#define __deref_out_ecount_full_opt(size) __deref_out_ecount_full(size) __post __deref __exceptthat __maybenull +#define __deref_out_bcount_full_opt(size) __deref_out_bcount_full(size) __post __deref __exceptthat __maybenull +#define __deref_out_z_opt __post __deref __valid __refparam __execeptthat __maybenull __post __deref __nullterminated +#define __deref_out_ecount_z_opt(size) __deref_out_ecount_opt(size) __post __deref __nullterminated +#define __deref_out_bcount_z_opt(size) __deref_out_bcount_opt(size) __post __deref __nullterminated +#define __deref_out_nz_opt __deref_out_opt +#define __deref_out_ecount_nz_opt(size) __deref_out_ecount_opt(size) +#define __deref_out_bcount_nz_opt(size) __deref_out_bcount_opt(size) +#define __deref_inout_opt __deref_inout __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_ecount_opt(size) __deref_inout_ecount(size) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_bcount_opt(size) __deref_inout_bcount(size) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_ecount_part_opt(size,length) __deref_inout_ecount_part(size,length) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_bcount_part_opt(size,length) __deref_inout_bcount_part(size,length) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_ecount_full_opt(size) __deref_inout_ecount_full(size) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_bcount_full_opt(size) __deref_inout_bcount_full(size) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_z_opt __deref_inout_opt __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_inout_ecount_z_opt(size) __deref_inout_ecount_opt(size) __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_inout_bcount_z_opt(size) __deref_inout_bcount_opt(size) __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_inout_nz_opt __deref_inout_opt +#define __deref_inout_ecount_nz_opt(size) __deref_inout_ecount_opt(size) +#define __deref_inout_bcount_nz_opt(size) __deref_inout_bcount_opt(size) +#define __deref_opt_ecount(size) __deref_ecount(size) __exceptthat __maybenull +#define __deref_opt_bcount(size) __deref_bcount(size) __exceptthat __maybenull +#define __deref_opt_out __deref_out __exceptthat __maybenull +#define __deref_opt_out_z __deref_opt_out __post __deref __nullterminated +#define __deref_opt_out_ecount(size) __deref_out_ecount(size) __exceptthat __maybenull +#define __deref_opt_out_bcount(size) __deref_out_bcount(size) __exceptthat __maybenull +#define __deref_opt_out_ecount_part(size,length) __deref_out_ecount_part(size,length) __exceptthat __maybenull +#define __deref_opt_out_bcount_part(size,length) __deref_out_bcount_part(size,length) __exceptthat __maybenull +#define __deref_opt_out_ecount_full(size) __deref_out_ecount_full(size) __exceptthat __maybenull +#define __deref_opt_out_bcount_full(size) __deref_out_bcount_full(size) __exceptthat __maybenull +#define __deref_opt_inout __deref_inout __exceptthat __maybenull +#define __deref_opt_inout_ecount(size) __deref_inout_ecount(size) __exceptthat __maybenull +#define __deref_opt_inout_bcount(size) __deref_inout_bcount(size) __exceptthat __maybenull +#define __deref_opt_inout_ecount_part(size,length) __deref_inout_ecount_part(size,length) __exceptthat __maybenull +#define __deref_opt_inout_bcount_part(size,length) __deref_inout_bcount_part(size,length) __exceptthat __maybenull +#define __deref_opt_inout_ecount_full(size) __deref_inout_ecount_full(size) __exceptthat __maybenull +#define __deref_opt_inout_bcount_full(size) __deref_inout_bcount_full(size) __exceptthat __maybenull +#define __deref_opt_inout_z __deref_opt_inout __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_opt_inout_ecount_z(size) __deref_opt_inout_ecount(size) __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_opt_inout_bcount_z(size) __deref_opt_inout_bcount(size) __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_opt_inout_nz __deref_opt_inout +#define __deref_opt_inout_ecount_nz(size) __deref_opt_inout_ecount(size) +#define __deref_opt_inout_bcount_nz(size) __deref_opt_inout_bcount(size) +#define __deref_opt_ecount_opt(size) __deref_ecount_opt(size) __exceptthat __maybenull +#define __deref_opt_bcount_opt(size) __deref_bcount_opt(size) __exceptthat __maybenull +#define __deref_opt_out_opt __deref_out_opt __exceptthat __maybenull +#define __deref_opt_out_ecount_opt(size) __deref_out_ecount_opt(size) __exceptthat __maybenull +#define __deref_opt_out_bcount_opt(size) __deref_out_bcount_opt(size) __exceptthat __maybenull +#define __deref_opt_out_ecount_part_opt(size,length) __deref_out_ecount_part_opt(size,length) __exceptthat __maybenull +#define __deref_opt_out_bcount_part_opt(size,length) __deref_out_bcount_part_opt(size,length) __exceptthat __maybenull +#define __deref_opt_out_ecount_full_opt(size) __deref_out_ecount_full_opt(size) __exceptthat __maybenull +#define __deref_opt_out_bcount_full_opt(size) __deref_out_bcount_full_opt(size) __exceptthat __maybenull +#define __deref_opt_out_z_opt __post __deref __valid __refparam __exceptthat __maybenull __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull __post __deref __nullterminated +#define __deref_opt_out_ecount_z_opt(size) __deref_opt_out_ecount_opt(size) __post __deref __nullterminated +#define __deref_opt_out_bcount_z_opt(size) __deref_opt_out_bcount_opt(size) __post __deref __nullterminated +#define __deref_opt_out_nz_opt __deref_opt_out_opt +#define __deref_opt_out_ecount_nz_opt(size) __deref_opt_out_ecount_opt(size) +#define __deref_opt_out_bcount_nz_opt(size) __deref_opt_out_bcount_opt(size) +#define __deref_opt_inout_opt __deref_inout_opt __exceptthat __maybenull +#define __deref_opt_inout_ecount_opt(size) __deref_inout_ecount_opt(size) __exceptthat __maybenull +#define __deref_opt_inout_bcount_opt(size) __deref_inout_bcount_opt(size) __exceptthat __maybenull +#define __deref_opt_inout_ecount_part_opt(size,length) __deref_inout_ecount_part_opt(size,length) __exceptthat __maybenull +#define __deref_opt_inout_bcount_part_opt(size,length) __deref_inout_bcount_part_opt(size,length) __exceptthat __maybenull +#define __deref_opt_inout_ecount_full_opt(size) __deref_inout_ecount_full_opt(size) __exceptthat __maybenull +#define __deref_opt_inout_bcount_full_opt(size) __deref_inout_bcount_full_opt(size) __exceptthat __maybenull +#define __deref_opt_inout_z_opt __deref_opt_inout_opt __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_opt_inout_ecount_z_opt(size) __deref_opt_inout_ecount_opt(size) __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_opt_inout_bcount_z_opt(size) __deref_opt_inout_bcount_opt(size) __pre __deref __nullterminated __post __deref __nullterminated +#define __deref_opt_inout_nz_opt __deref_opt_inout_opt +#define __deref_opt_inout_ecount_nz_opt(size) __deref_opt_inout_ecount_opt(size) +#define __deref_opt_inout_bcount_nz_opt(size) __deref_opt_inout_bcount_opt(size) + +/* +------------------------------------------------------------------------------- +Advanced Annotation Definitions + +Any of these may be used to directly annotate functions, and may be used in +combination with each other or with regular buffer macros. For an explanation +of each annotation, see the advanced annotations section. +------------------------------------------------------------------------------- +*/ + +#define __success(expr) __inner_success(expr) +#define __nullterminated __readableTo(sentinel(0)) +#define __nullnullterminated +#define __reserved __pre __null +#define __checkReturn __inner_checkReturn +#define __typefix(ctype) __inner_typefix(ctype) +#define __override __inner_override +#define __callback __inner_callback +#define __format_string +#define __blocksOn(resource) __inner_blocksOn(resource) +#define __control_entrypoint(category) __inner_control_entrypoint(category) +#define __data_entrypoint(category) __inner_data_entrypoint(category) + +#ifndef __fallthrough + __inner_fallthrough_dec + #define __fallthrough __inner_fallthrough +#endif + +#ifndef __analysis_assume +#ifdef _PREFAST_ +#define __analysis_assume(expr) __assume(expr) +#else +#define __analysis_assume(expr) +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif //__specstrings \ No newline at end of file diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstring.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstring.h new file mode 100644 index 0000000..7cc2f13 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstring.h @@ -0,0 +1,342 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#ifndef _WMSPECSTRING_H_ +#define _WMSPECSTRING_H_ + +#if (!defined UNDER_CE && !defined NO_WINDOWS && !defined SPECSTRINGS_H) +#define SPECSTRINGS_H +/************************************************************************* +* See specstrings_strict.h for documentation of all user visible macros. +*************************************************************************/ +#if _MSC_VER +#pragma once +#endif +#include + +#ifndef __SAL_H_FULL_VER +#define __SAL_H_FULL_VER 140050727 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* version specific fixes to bring sal.h upto date */ +#if __SAL_H_FULL_VER <= 140050727 + +/* Missing from RTM sal.h */ +#if !defined(__midl) && defined(_PREFAST_) && _MSC_VER >= 1000 + +#define __inexpressible_readableTo(size) __declspec("SAL_readableTo(inexpressibleCount('" SPECSTRINGIZE(size) "'))") +#define __inexpressible_writableTo(size) __declspec("SAL_writableTo(inexpressibleCount('" SPECSTRINGIZE(size) "'))") +#define __inner_bound __declspec("SAL_bound") +#define __inner_range(lb,ub) __declspec("SAL_range(" SPECSTRINGIZE(lb) "," SPECSTRINGIZE(ub) ")") +#define __inner_assume_bound_dec __inline __nothrow void __AssumeBoundInt(__post __inner_bound int i) {i;} +#define __inner_assume_bound(i) __AssumeBoundInt(i); +#define __inner_allocator __declspec("SAL_allocator") +#else +#define __inexpressible_readableTo(size) +#define __inexpressible_writableTo(size) +#define __inner_bound +#define __inner_range(lb,ub) +#define __inner_assume_bound_dec +#define __inner_assume_bound(i) +#define __inner_allocator +#endif + +#define __xcount(size) __notnull __inexpressible_writableTo(size) +#define __in_xcount(size) __in __pre __inexpressible_readableTo(size) +#define __out_xcount(size) __xcount(size) __post __valid __refparam +#define __out_xcount_part(size,length) __out_xcount(size) __post __inexpressible_readableTo(length) +#define __out_xcount_full(size) __out_xcount_part(size,size) +#define __inout_xcount(size) __out_xcount(size) __pre __valid +#define __inout_xcount_part(size,length) __out_xcount_part(size,length) __pre __valid __pre __inexpressible_readableTo(length) +#define __inout_xcount_full(size) __inout_xcount_part(size,size) +#define __xcount_opt(size) __xcount(size) __exceptthat __maybenull +#define __in_xcount_opt(size) __in_xcount(size) __exceptthat __maybenull +#define __out_xcount_opt(size) __out_xcount(size) __exceptthat __maybenull +#define __out_xcount_part_opt(size,length) __out_xcount_part(size,length) __exceptthat __maybenull +#define __out_xcount_full_opt(size) __out_xcount_full(size) __exceptthat __maybenull +#define __inout_xcount_opt(size) __inout_xcount(size) __exceptthat __maybenull +#define __inout_xcount_part_opt(size,length) __inout_xcount_part(size,length) __exceptthat __maybenull +#define __inout_xcount_full_opt(size) __inout_xcount_full(size) __exceptthat __maybenull +#define __deref_xcount(size) __ecount(1) __post __elem_readableTo(1) __post __deref __notnull __post __deref __inexpressible_writableTo(size) +#define __deref_in __in __pre __deref __deref __readonly +#define __deref_in_ecount(size) __deref_in __pre __deref __elem_readableTo(size) +#define __deref_in_bcount(size) __deref_in __pre __deref __byte_readableTo(size) +#define __deref_in_xcount(size) __deref_in __pre __deref __inexpressible_readableTo(size) +#define __deref_out_xcount(size) __deref_xcount(size) __post __deref __valid __refparam +#define __deref_out_xcount_part(size,length) __deref_out_xcount(size) __post __deref __inexpressible_readableTo(length) +#define __deref_out_xcount_full(size) __deref_out_xcount_part(size,size) +#define __deref_out_xcount(size) __deref_xcount(size) __post __deref __valid __refparam +#define __inout_xcount_opt(size) __inout_xcount(size) __exceptthat __maybenull +#define __inout_xcount_part_opt(size,length) __inout_xcount_part(size,length) __exceptthat __maybenull +#define __inout_xcount_full_opt(size) __inout_xcount_full(size) __exceptthat __maybenull +#define __deref_xcount(size) __ecount(1) __post __elem_readableTo(1) __post __deref __notnull __post __deref __inexpressible_writableTo(size) +#define __deref_in __in __pre __deref __deref __readonly +#define __deref_in_ecount(size) __deref_in __pre __deref __elem_readableTo(size) +#define __deref_in_bcount(size) __deref_in __pre __deref __byte_readableTo(size) +#define __deref_in_xcount(size) __deref_in __pre __deref __inexpressible_readableTo(size) +#define __deref_out_xcount(size) __deref_xcount(size) __post __deref __valid __refparam +#define __deref_out_xcount_part(size,length) __deref_out_xcount(size) __post __deref __inexpressible_readableTo(length) +#define __deref_out_xcount_full(size) __deref_out_xcount_part(size,size) +#define __deref_out_xcount(size) __deref_xcount(size) __post __deref __valid __refparam +#define __deref_inout_xcount(size) __deref_inout __pre __deref __inexpressible_writableTo(size) __post __deref __inexpressible_writableTo(size) +#define __deref_inout_xcount_part(size,length) __deref_inout_xcount(size) __pre __deref __inexpressible_readableTo(length) __post __deref __inexpressible_readableTo(length) +#define __deref_inout_xcount_full(size) __deref_inout_xcount_part(size,size) +#define __deref_xcount_opt(size) __deref_xcount(size) __post __deref __exceptthat __maybenull +#define __deref_in_opt __deref_in __pre __deref __exceptthat __maybenull +#define __deref_in_ecount_opt(size) __deref_in_ecount(size) __pre __deref __exceptthat __maybenull +#define __deref_in_bcount_opt(size) __deref_in_bcount(size) __pre __deref __exceptthat __maybenull +#define __deref_in_xcount_opt(size) __deref_in_xcount(size) __pre __deref __exceptthat __maybenull +#define __deref_out_xcount_opt(size) __deref_out_xcount(size) __post __deref __exceptthat __maybenull +#define __deref_out_xcount_part_opt(size,length) __deref_out_xcount_part(size,length) __post __deref __exceptthat __maybenull +#define __deref_out_xcount_full_opt(size) __deref_out_xcount_full(size) __post __deref __exceptthat __maybenull +#define __deref_inout_xcount_opt(size) __deref_inout_xcount(size) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_xcount_part_opt(size,length) __deref_inout_xcount_part(size,length) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_inout_xcount_full_opt(size) __deref_inout_xcount_full(size) __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull +#define __deref_opt_xcount(size) __deref_xcount(size) __exceptthat __maybenull +#define __deref_opt_in __deref_in __exceptthat __maybenull +#define __deref_opt_in_ecount(size) __deref_in_ecount(size) __exceptthat __maybenull +#define __deref_opt_in_bcount(size) __deref_in_bcount(size) __exceptthat __maybenull +#define __deref_opt_in_xcount(size) __deref_in_xcount(size) __exceptthat __maybenull +#define __deref_opt_out_xcount(size) __deref_out_xcount(size) __exceptthat __maybenull +#define __deref_opt_out_xcount_part(size,length) __deref_out_xcount_part(size,length) __exceptthat __maybenull +#define __deref_opt_out_xcount_full(size) __deref_out_xcount_full(size) __exceptthat __maybenull +#define __deref_opt_inout_xcount(size) __deref_inout_xcount(size) __exceptthat __maybenull +#define __deref_opt_inout_xcount_part(size,length) __deref_inout_xcount_part(size,length) __exceptthat __maybenull +#define __deref_opt_inout_xcount_full(size) __deref_inout_xcount_full(size) __exceptthat __maybenull +#define __deref_opt_xcount_opt(size) __deref_xcount_opt(size) __exceptthat __maybenull +#define __deref_opt_in_opt __deref_in_opt __exceptthat __maybenull +#define __deref_opt_in_ecount_opt(size) __deref_in_ecount_opt(size) __exceptthat __maybenull +#define __deref_opt_in_bcount_opt(size) __deref_in_bcount_opt(size) __exceptthat __maybenull +#define __deref_opt_in_xcount_opt(size) __deref_in_xcount_opt(size) __exceptthat __maybenull +#define __deref_opt_out_xcount_opt(size) __deref_out_xcount_opt(size) __exceptthat __maybenull +#define __deref_opt_out_xcount_part_opt(size,length) __deref_out_xcount_part_opt(size,length) __exceptthat __maybenull +#define __deref_opt_out_xcount_full_opt(size) __deref_out_xcount_full_opt(size) __exceptthat __maybenull +#define __deref_opt_inout_xcount_opt(size) __deref_inout_xcount_opt(size) __exceptthat __maybenull +#define __deref_opt_inout_xcount_part_opt(size,length) __deref_inout_xcount_part_opt(size,length) __exceptthat __maybenull +#define __deref_opt_inout_xcount_full_opt(size) __deref_inout_xcount_full_opt(size) __exceptthat __maybenull +/* Must protect redfinitions of macros to workaround rc.exe issues. */ +#ifndef RC_INVOKED +#undef __nullnullterminated +#define __nullnullterminated __xcount("string terminated by two nulls") +#undef __checkReturn +#define __checkReturn __post __inner_checkReturn +#endif +#endif //__SAL_H_FULL_VER <= 140050727 + +/************************************************************************ + New extensions to sal.h follow here. +*************************************************************************/ + +#if (_MSC_VER >= 1000) && !defined(__midl) && defined(_PREFAST_) +#define __file_parser(typ) __declspec("SAL_file_parser(function, " #typ ")") +#define __file_parser_class(typ) __declspec("SAL_file_parser(class, " #typ ")") +#define __file_parser_library(typ) extern int __declspec("SAL_file_parser(library, " #typ ")") __iSALFileParserLibrary##typ; +#define __source_code_content(typ) extern int __declspec("SAL_source_code_content(" #typ ")") __iSAL_Source_Code_Content##typ; +#define __class_code_content(typ) __declspec("SAL_class_code_content(" #typ ")") +#define __analysis_assert(e) __assume(e) +#define __analysis_hint(hint) __declspec("SAL_analysisHint(" #hint ")") +/* Internal defintions */ +#define __inner_data_source(src_raw) __declspec("SAL_untrusted_data_source(" src_raw ")") +#define __inner_this_data_source(src_raw) __declspec("SAL_untrusted_data_source_this(" src_raw ")") +#define __inner_out_validated(typ_raw) __declspec("SAL_post") __declspec("SAL_validated(" typ_raw ")") +#define __inner_this_out_validated(typ_raw) __declspec("SAL_validated_this(" typ_raw ")") +#define __inner_assume_validated_dec __inline __nothrow void __AssumeValidated(__inner_out_validated("BY_DESIGN") const void *p) {p;} +#define __inner_assume_validated(p) __AssumeValidated(p) +#define __inner_transfer(formal) __declspec("SAL_transfer_adt_property_from(" SPECSTRINGIZE(formal) ")") +#define __inner_encoded __declspec("SAL_encoded") + +#define __$adt_prop(adt,prop) __declspec("SAL_adt("#adt","#prop")") +#define __$adt_add_prop(adt,prop) __declspec("SAL_add_adt_property("#adt","#prop")") +#define __$adt_remove_prop(adt,prop) __declspec("SAL_remove_adt_property("#adt","#prop")") +#define __$adt_transfer_prop(arg) __declspec("SAL_transfer_adt_property_from("#arg")") +#define __$adt_type_props(typ) __declspec("SAL_post_type("#typ")") +#define __$volatile __declspec("SAL_volatile") +#define __$nonvolatile __declspec("SAL_nonvolatile") +#define __$possibly_notnulltermiated __declspec("SAL_RequiresZeroTermination(sometimes)") +#else +#define __file_parser(typ) +#define __file_parser_class(typ) +#define __file_parser_library(typ) +#define __source_code_content(typ) +#define __class_code_content(typ) +#define __analysis_assert(e) +#define __analysis_hint(hint) +/* Internal defintions */ +#define __inner_data_source(src_raw) +#define __inner_this_data_source(src_raw) +#define __inner_out_validated(typ_raw) +#define __inner_this_out_validated(typ_raw) +#define __inner_assume_validated_dec +#define __inner_assume_validated(p) +#define __inner_transfer(formal) +#define __inner_encoded +#define __$adt_prop(adt,prop) +#define __$adt_add_prop(adt,prop) +#define __$adt_remove_prop(adt,prop) +#define __$adt_transfer_prop(arg) +#define __$adt_type_props(typ) +#define __$volatile +#define __$nonvolatile +#define __$possibly_notnulltermiated +#endif // #if (_MSC_VER >= 1000) && !defined(__midl) && defined(_PREFAST_) + +#define __field_ecount(size) __notnull __elem_writableTo(size) +#define __field_bcount(size) __notnull __byte_writableTo(size) +#define __field_xcount(size) __notnull __inexpressible_writableTo(size) + +#define __field_ecount_opt(size) __maybenull __elem_writableTo(size) +#define __field_bcount_opt(size) __maybenull __byte_writableTo(size) +#define __field_xcount_opt(size) __maybenull __inexpressible_writableTo(size) + +#define __field_ecount_part(size,init) __notnull __elem_writableTo(size) __elem_readableTo(init) +#define __field_bcount_part(size,init) __notnull __byte_writableTo(size) __byte_readableTo(init) +#define __field_xcount_part(size,init) __notnull __inexpressible_writableTo(size) __inexpressible_readableTo(init) + +#define __field_ecount_part_opt(size,init) __maybenull __elem_writableTo(size) __elem_readableTo(init) +#define __field_bcount_part_opt(size,init) __maybenull __byte_writableTo(size) __byte_readableTo(init) +#define __field_xcount_part_opt(size,init) __maybenull __inexpressible_writableTo(size) __inexpressible_readableTo(init) + +#define __field_ecount_full(size) __field_ecount_part(size,size) +#define __field_bcount_full(size) __field_bcount_part(size,size) +#define __field_xcount_full(size) __field_xcount_part(size,size) + +#define __field_ecount_full_opt(size) __field_ecount_part_opt(size,size) +#define __field_bcount_full_opt(size) __field_bcount_part_opt(size,size) +#define __field_xcount_full_opt(size) __field_xcount_part_opt(size,size) + +#define __struct_bcount(size) __field_bcount(size) +#define __struct_xcount(size) __field_xcount(size) + +#if !defined(__out_awcount) +#define __out_awcount(expr,size) __pre __notnull \ + __byte_writableTo((expr) ? (size) : (size) * 2) \ + __post __valid __refparam +#endif +#if !defined(__in_awcount) +#define __in_awcount(expr,size) __pre __valid \ + __pre __deref __readonly \ + __byte_readableTo((expr) ? (size) : (size) * 2) +#endif + +/* integer related macros */ +#define __allocator __inner_allocator +#define __bound __inner_bound +#define __range(lb,ub) __inner_range(lb,ub) +#define __in_bound __pre __inner_bound +#define __out_bound __post __inner_bound +#define __deref_out_bound __post __deref __inner_bound +#define __in_range(lb,ub) __pre __inner_range(lb,ub) +#define __out_range(lb,ub) __post __inner_range(lb,ub) +#define __deref_in_range(lb,ub) __pre __deref __inner_range(lb,ub) +#define __deref_out_range(lb,ub) __post __deref __inner_range(lb,ub) +#define __field_range(lb,ub) __range(lb,ub) +#define __field_data_source(src_sym) __inner_data_source(#src_sym) + +/* Pentraion review macros */ +#define __in_data_source(src_sym) __pre __inner_data_source(#src_sym) +#define __out_data_source(src_sym) __post __inner_data_source(#src_sym) +#define __out_validated(typ_sym) __inner_out_validated(#typ_sym) +#define __this_out_data_source(src_sym) __inner_this_data_source(#src_sym) +#define __this_out_validated(typ_sym) __inner_this_out_validated(#typ_sym) +#define __transfer(formal) __post __inner_transfer(formal) +#define __rpc_entry __inner_control_entrypoint(RPC) +#define __kernel_entry __inner_control_entrypoint(UserToKernel) +#define __gdi_entry __inner_control_entrypoint(GDI) +#define __encoded_pointer __inner_encoded +#define __encoded_array __inner_encoded +#define __field_encoded_pointer __inner_encoded +#define __field_encoded_array __inner_encoded +#define __type_has_adt_prop(adt,prop) __$adt_prop(adt,prop) +#define __out_has_adt_prop(adt,prop) __post __$adt_add_prop(adt,prop) +#define __out_not_has_adt_prop(adt,prop) __post __$adt_remove_prop(adt,prop) +#define __out_transfer_adt_prop(arg) __post __$adt_transfer_prop(arg) +#define __out_has_type_adt_props(typ) __post __$adt_type_props(typ) + +/* useful PFD related macros */ +#define __possibly_notnulltermiated __post __$possibly_notnulltermiated + +#if defined(_WINDOWS_) +/* Windows Internal */ +#define __volatile __$volatile +#define __nonvolatile __$nonvolatile +#define __deref_volatile __deref __volatile +#define __deref_nonvolatile __deref __nonvolatile +#endif + +/* declare stub functions for macros */ +__inner_assume_validated_dec +__inner_assume_bound_dec + +#define __assume_validated(p) __inner_assume_validated(p) +#define __assume_bound(i) __inner_assume_bound(i) +#ifdef __cplusplus +} +#endif +#include +#ifdef _PREFIX_ +/************************************************************************** +* Defintion of __pfx_assume and __pfx_assert. Thse should be the only +* defintions of these functions. +***************************************************************************/ +#if __cplusplus +extern "C" void __pfx_assert(bool, const char *); +extern "C" void __pfx_assume(bool, const char *); +#else +void __pfx_assert(int, const char *); +void __pfx_assume(int, const char *); +#endif +/************************************************************************** +* Redefintion of __analysis_assume and __analysis_assert for PREFIX build +**************************************************************************/ +#undef __analysis_assume +#undef __analysis_assert +#define __analysis_assume(e) (__pfx_assume(e,"pfx_assume"),__assume(e)); +#define __analysis_assert(e) (__pfx_assert(e,"pfx_assert"),__assume(e)); +#endif /* ifdef _PREFIX_ */ + +/************************************************************************** +* This include should always be the last thing in this file. +* Must avoid redfinitions of macros to workaround rc.exe issues. +***************************************************************************/ +#if !(defined(RC_INVOKED) || defined(SORTPP_PASS)) +#include +#endif /* if !(defined(RC_INVOKED) || defined(SORTPP_PASS)) */ +#endif /* #ifndef SPECSTRINGS_H */ + +// Some CE versions don't have specstrings.h, some have very old version without +// __specstrings defined. So we handle CE separately in wmasalce.h +#if defined(UNDER_CE) || defined(NO_WINDOWS) + #include "wmspecstringce.h" +#endif + +#endif //_WMSPECSTRING_H_ + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_adt.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_adt.h new file mode 100644 index 0000000..1c7b814 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_adt.h @@ -0,0 +1,71 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#pragma once +/************************************************************************* +* DEFINITIONS OF NEW TYPES +*************************************************************************/ +#if !defined(__midl) +#define __$compname_props \ + __type_has_adt_prop(compname,nullterminated) \ + __type_has_adt_prop(compname,valid_schars) \ + __type_has_adt_prop(compname,correct_len) \ + __nullterminated +#if defined(UNICODE) || defined(_UNICODE) +#define __$TCHAR unsigned short +#else +#define __$TCHAR char +#endif +typedef __$compname_props char* ValidCompNameA; +typedef __$compname_props unsigned short* ValidCompNameW; +typedef __$compname_props const unsigned short* ConstValidCompNameW; +typedef __$compname_props __$TCHAR* SAL_ValidCompNameT; +typedef __$compname_props const __$TCHAR* SAL_ConstValidCompNameT; +#undef __$compname_props +#undef __$TCHAR +#endif + +/************************************************************************* +* DEFINITIONS OF INLINE FUNCTIONS FOR CASTING TO THE NEW TYPES : USER +*************************************************************************/ +#if (_MSC_VER >= 1000) && !defined(__midl) && defined(_PREFAST_) +#ifdef __cplusplus +extern "C" { +#endif +void __inline __nothrow __SAL_ValidCompNameA(__out_has_type_adt_props(ValidCompNameA) const void *expr) { expr;} +void __inline __nothrow __SAL_ValidCompNameW(__out_has_type_adt_props(ValidCompNameW) const void *expr) { expr;} +#ifdef __cplusplus +} +#endif +#define __assume_ValidCompNameA(expr) __SAL_ValidCompNameA(expr) +#define __assume_ValidCompNameW(expr) __SAL_ValidCompNameW(expr) +#else +#define __assume_ValidCompNameA(expr) +#define __assume_ValidCompNameW(expr) +#endif + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_strict.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_strict.h new file mode 100644 index 0000000..93b876c --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_strict.h @@ -0,0 +1,1096 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + + +/************************************************************************* +* This file documents all the macros approved for use in windows source +* code. It includes some experimental macros which should only be used by +* experts. +* +* DO NOT include this file directly. This file is include after +* specstrings.h. So we can undefine every possible old definition including +* private internal macros people should not be using, as well as macros from +* sal.h. Macros are redefined here in a way to cause syntax errors when used +* incorrectly during a normal build when specstrings.h is included and +* __SPECSTRINGS_STRICT_LEVEL is defined. +* +* There are several levels of strictness, each level includes the behavior of +* all previous levels. +* +* 0 - Disable strict checking +* 1 - Break on unapproved macros and misuse of statement +* macros such as __fallthrough (default) +* 2 - Deprecated some old macros that should not be used +* 3 - Use VS 2005 Source Annotation to make sure every macro +* is used in the right context. For example placing __in on a return +* parameter will result in an error. +************************************************************************/ +#ifndef __SPECSTRINGS_STRICT_LEVEL +#define __SPECSTRINGS_STRICT_LEVEL 1 +#endif +/************************************************************************ +* Introduction +* +* specstrings.h provides a set of annotations to describe how a function uses +* its parameters - the assumptions it makes about them, and the guarantees it +* makes upon finishing. +* +* Annotations must be placed before a function parameter's type or its return +* type. There are two basic classes of common annotations buffer annotations +* and advanced annotations. Buffer annotations describe how functions use +* their pointer parameters, and advanced annotations either describe +* complex/unusual buffer behavior, or provide additional information about a +* parameter that is not otherwise expressible. +* +* Buffer Annotations +* +* The most important annotations in SpecStrings.h provide a consistent way to +* annotate buffer parameters or return values for a function. Each of these +* annotations describes a single buffer (which could be a string, a +* fixed-length or variable-length array, or just a pointer) that the function +* interacts with: where it is, how large it is, how much is initialized, and +* what the function does with it. +* +* The appropriate macro for a given buffer can be constructed using the table +* below. Just pick the appropriate values from each category, and combine +* them together with a leading underscore. Some combinations of values do not +* make sense as buffer annotations. Only meaningful annotations can be added +* to your code; for a list of these, see the buffer annotation definitions +* section. +* +* Only a single buffer annotation should be used for each parameter. +* +* |------------|------------|---------|--------|----------|---------------| +* | Level | Usage | Size | Output | Optional | Parameters | +* |------------|------------|---------|--------|----------|---------------| +* | <> | <> | <> | <> | <> | <> | +* | _deref | _in | _ecount | _full | _opt | (size) | +* | _deref_opt | _out | _bcount | _part | | (size,length) | +* | | _inout | | | | | +* | | | | | | | +* |------------|------------|---------|--------|----------|---------------| +* +* Note: "<>" represents the empty string. +* +* Level: Describes the buffer pointer's level of indirection from the +* parameter or return value 'p'. +* +* <> : p is the buffer pointer. +* _deref : *p is the buffer pointer. p must not be NULL. +* _deref_opt : *p may be the buffer pointer. p may be NULL, in which case the +* rest of the annotation is ignored. +* +* Usage: Describes how the function uses the buffer. +* +* <> : The buffer is not accessed. If used on the return value or with +* _deref, the function will provide the buffer, and it will be uninitialized +* at exit. Otherwise, the caller must provide the buffer. This should only +* be used for alloc and free functions. +* +* _in : The function will only read from the buffer. The caller must provide +* the buffer and initialize it. +* +* _out : The function will only write to the buffer. If used on the return +* value or with _deref, the function will provide the buffer and initialize +* it. Otherwise, the caller must provide the buffer, and the function will +* initialize it. +* +* _inout : The function may freely read from and write to the buffer. The +* caller must provide the buffer and initialize it. If used with _deref, the +* buffer may be reallocated by the function. +* +* Size: Describes the total size of the buffer. This may be less than the +* space actually allocated for the buffer, in which case it describes the +* accessible amount. +* +* <> : No buffer size is given. If the type specifies the buffer size (such +* as with LPSTR and LPWSTR), that amount is used. Otherwise, the buffer is +* one element long. Must be used with _in, _out, or _inout. +* +* _ecount : The buffer size is an explicit element count. +* +* _bcount : The buffer size is an explicit byte count. +* +* Output: Describes how much of the buffer will be initialized by the +* function. For _inout buffers, this also describes how much is initialized +* at entry. Omit this category for _in buffers; they must be fully +* initialized by the caller. +* +* <> : The type specifies how much is initialized. For instance, a function +* initializing an LPWSTR must NULL-terminate the string. +* +* _full : The function initializes the entire buffer. +* +* _part : The function initializes part of the buffer, and explicitly +* indicates how much. +* +* Optional: Describes if the buffer itself is optional. +* +* <> : The pointer to the buffer must not be NULL. +* +* _opt : The pointer to the buffer might be NULL. It will be checked before +* being dereferenced. +* +* Parameters: Gives explicit counts for the size and length of the buffer. +* +* <> : There is no explicit count. Use when neither _ecount nor _bcount is +* used. +* +* (size) : Only the buffer's total size is given. Use with _ecount or _bcount +* but not _part. +* +* (size,length) : The buffer's total size and initialized length are +* given. Use with _ecount_part and _bcount_part. +* +* ---------------------------------------------------------------------------- +* Buffer Annotation Examples +* +* LWSTDAPI_(BOOL) StrToIntExA( +* LPCSTR pszString, // No annotation required, const implies __in. +* DWORD dwFlags, +* __out int *piRet // A pointer whose dereference will be filled in. +* ); +* +* void MyPaintingFunction( +* __in HWND hwndControl, // An initialized read-only parameter. +* __in_opt HDC hdcOptional, // An initialized read-only parameter that +* // might be NULL. +* __inout IPropertyStore *ppsStore // An initialized parameter that +* // may be freely used and modified. +* ); +* +* LWSTDAPI_(BOOL) PathCompactPathExA( +* __out_ecount(cchMax) LPSTR pszOut, // A string buffer with cch elements +* // that will be '\0' terminated +* // on exit. +* LPCSTR pszSrc, // No annotation required, +* // const implies __in. +* UINT cchMax, +* DWORD dwFlags +* ); +* +* HRESULT SHLocalAllocBytes( +* size_t cb, +* __deref_bcount(cb) T **ppv // A pointer whose dereference will be set +* // to an uninitialized buffer with cb bytes. +* ); +* +* __inout_bcount_full(cb) : A buffer with cb elements that is fully +* initialized at entry and exit, and may be written to by this function. +* +* __out_ecount_part(count, *countOut) : A buffer with count elements that +* will be partially initialized by this function. The function indicates how +* much it initialized by setting *countOut. +* +************************************************************************/ +#if (_MSC_VER >= 1400) && !defined(__midl) && !defined(_PREFAST_) && (__SPECSTRINGS_STRICT_LEVEL > 0) +#pragma once +#include +#define __ecount(size) __allowed(on_return) +#define __bcount(size) __allowed(on_return) +#define __xcount(size) __allowed(on_return) +#define __in __allowed(on_parameter) +#define __in_ecount(size) __allowed(on_parameter) +#define __in_bcount(size) __allowed(on_parameter) +#define __in_xcount(size) __allowed(on_parameter) +#define __in_z __allowed(on_parameter) +#define __in_ecount_z(size) __allowed(on_parameter) +#define __in_bcount_z(size) __allowed(on_parameter) +#define __out __allowed(on_parameter) +#define __out_ecount(size) __allowed(on_parameter) +#define __out_bcount(size) __allowed(on_parameter) +#define __out_xcount(size) __allowed(on_parameter) +#define __out_ecount_part(size,len) __allowed(on_parameter) +#define __out_bcount_part(size,len) __allowed(on_parameter) +#define __out_xcount_part(size,len) __allowed(on_parameter) +#define __out_ecount_full(size) __allowed(on_parameter) +#define __out_bcount_full(size) __allowed(on_parameter) +#define __out_xcount_full(size) __allowed(on_parameter) +#define __out_z __allowed(on_parameter) +#define __out_ecount_z(size) __allowed(on_parameter) +#define __out_bcount_z(size) __allowed(on_parameter) +#define __inout __allowed(on_parameter) +#define __inout_ecount(size) __allowed(on_parameter) +#define __inout_bcount(size) __allowed(on_parameter) +#define __inout_xcount(size) __allowed(on_parameter) +#define __inout_ecount_part(size,len) __allowed(on_parameter) +#define __inout_bcount_part(size,len) __allowed(on_parameter) +#define __inout_xcount_part(size,len) __allowed(on_parameter) +#define __inout_ecount_full(size) __allowed(on_parameter) +#define __inout_bcount_full(size) __allowed(on_parameter) +#define __inout_xcount_full(size) __allowed(on_parameter) +#define __inout_z __allowed(on_parameter) +#define __inout_ecount_z(size) __allowed(on_parameter) +#define __inout_bcount_z(size) __allowed(on_parameter) +#define __ecount_opt(size) __allowed(on_parameter) +#define __bcount_opt(size) __allowed(on_parameter) +#define __xcount_opt(size) __allowed(on_parameter) +#define __in_opt __allowed(on_parameter) +#define __in_ecount_opt(size) __allowed(on_parameter) +#define __in_bcount_opt(size) __allowed(on_parameter) +#define __in_z_opt __allowed(on_parameter) +#define __in_ecount_z_opt(size) __allowed(on_parameter) +#define __in_bcount_z_opt(size) __allowed(on_parameter) +#define __in_xcount_opt(size) __allowed(on_parameter) +#define __out_opt __allowed(on_parameter) +#define __out_ecount_opt(size) __allowed(on_parameter) +#define __out_bcount_opt(size) __allowed(on_parameter) +#define __out_xcount_opt(size) __allowed(on_parameter) +#define __out_ecount_part_opt(size,len) __allowed(on_parameter) +#define __out_bcount_part_opt(size,len) __allowed(on_parameter) +#define __out_xcount_part_opt(size,len) __allowed(on_parameter) +#define __out_ecount_full_opt(size) __allowed(on_parameter) +#define __out_bcount_full_opt(size) __allowed(on_parameter) +#define __out_xcount_full_opt(size) __allowed(on_parameter) +#define __out_ecount_z_opt(size) __allowed(on_parameter) +#define __out_bcount_z_opt(size) __allowed(on_parameter) +#define __inout_opt __allowed(on_parameter) +#define __inout_ecount_opt(size) __allowed(on_parameter) +#define __inout_bcount_opt(size) __allowed(on_parameter) +#define __inout_xcount_opt(size) __allowed(on_parameter) +#define __inout_ecount_part_opt(size,len) __allowed(on_parameter) +#define __inout_bcount_part_opt(size,len) __allowed(on_parameter) +#define __inout_xcount_part_opt(size,len) __allowed(on_parameter) +#define __inout_ecount_full_opt(size) __allowed(on_parameter) +#define __inout_bcount_full_opt(size) __allowed(on_parameter) +#define __inout_xcount_full_opt(size) __allowed(on_parameter) +#define __inout_z_opt __allowed(on_parameter) +#define __inout_ecount_z_opt(size) __allowed(on_parameter) +#define __inout_ecount_z_opt(size) __allowed(on_parameter) +#define __inout_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_ecount(size) __allowed(on_parameter) +#define __deref_bcount(size) __allowed(on_parameter) +#define __deref_xcount(size) __allowed(on_parameter) +#define __deref_in __allowed(on_parameter) +#define __deref_in_ecount(size) __allowed(on_parameter) +#define __deref_in_bcount(size) __allowed(on_parameter) +#define __deref_in_xcount(size) __allowed(on_parameter) +#define __deref_out __allowed(on_parameter) +#define __deref_out_ecount(size) __allowed(on_parameter) +#define __deref_out_bcount(size) __allowed(on_parameter) +#define __deref_out_xcount(size) __allowed(on_parameter) +#define __deref_out_ecount_part(size,len) __allowed(on_parameter) +#define __deref_out_bcount_part(size,len) __allowed(on_parameter) +#define __deref_out_xcount_part(size,len) __allowed(on_parameter) +#define __deref_out_ecount_full(size) __allowed(on_parameter) +#define __deref_out_bcount_full(size) __allowed(on_parameter) +#define __deref_out_xcount_full(size) __allowed(on_parameter) +#define __deref_out_z __allowed(on_parameter) +#define __deref_out_ecount_z(size) __allowed(on_parameter) +#define __deref_out_bcount_z(size) __allowed(on_parameter) +#define __deref_out_xcount(size) __allowed(on_parameter) +#define __deref_inout __allowed(on_parameter) +#define __deref_inout_ecount(size) __allowed(on_parameter) +#define __deref_inout_bcount(size) __allowed(on_parameter) +#define __deref_inout_xcount(size) __allowed(on_parameter) +#define __deref_inout_ecount_part(size,len) __allowed(on_parameter) +#define __deref_inout_bcount_part(size,len) __allowed(on_parameter) +#define __deref_inout_xcount_part(size,len) __allowed(on_parameter) +#define __deref_inout_ecount_full(size) __allowed(on_parameter) +#define __deref_inout_bcount_full(size) __allowed(on_parameter) +#define __deref_inout_xcount_full(size) __allowed(on_parameter) +#define __deref_inout_z __allowed(on_parameter) +#define __deref_inout_ecount_z(size) __allowed(on_parameter) +#define __deref_inout_bcount_z(size) __allowed(on_parameter) +#define __deref_ecount_opt(size) __allowed(on_parameter) +#define __deref_bcount_opt(size) __allowed(on_parameter) +#define __deref_xcount_opt(size) __allowed(on_parameter) +#define __deref_in_opt __allowed(on_parameter) +#define __deref_in_ecount_opt(size) __allowed(on_parameter) +#define __deref_in_bcount_opt(size) __allowed(on_parameter) +#define __deref_in_xcount_opt(size) __allowed(on_parameter) +#define __deref_out_opt __allowed(on_parameter) +#define __deref_out_ecount_opt(size) __allowed(on_parameter) +#define __deref_out_bcount_opt(size) __allowed(on_parameter) +#define __deref_out_xcount_opt(size) __allowed(on_parameter) +#define __deref_out_ecount_part_opt(size,len) __allowed(on_parameter) +#define __deref_out_bcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_out_xcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_out_ecount_full_opt(size) __allowed(on_parameter) +#define __deref_out_bcount_full_opt(size) __allowed(on_parameter) +#define __deref_out_xcount_full_opt(size) __allowed(on_parameter) +#define __deref_out_z_opt __allowed(on_parameter) +#define __deref_out_ecount_z_opt(size) __allowed(on_parameter) +#define __deref_out_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_inout_opt __allowed(on_parameter) +#define __deref_inout_ecount_opt(size) __allowed(on_parameter) +#define __deref_inout_bcount_opt(size) __allowed(on_parameter) +#define __deref_inout_xcount_opt(size) __allowed(on_parameter) +#define __deref_inout_ecount_part_opt(size,len) __allowed(on_parameter) +#define __deref_inout_bcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_inout_xcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_inout_ecount_full_opt(size) __allowed(on_parameter) +#define __deref_inout_bcount_full_opt(size) __allowed(on_parameter) +#define __deref_inout_xcount_full_opt(size) __allowed(on_parameter) +#define __deref_inout_z_opt __allowed(on_parameter) +#define __deref_inout_ecount_z_opt(size) __allowed(on_parameter) +#define __deref_inout_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_opt_ecount(size) __allowed(on_parameter) +#define __deref_opt_bcount(size) __allowed(on_parameter) +#define __deref_opt_xcount(size) __allowed(on_parameter) +#define __deref_opt_in __allowed(on_parameter) +#define __deref_opt_in_ecount(size) __allowed(on_parameter) +#define __deref_opt_in_bcount(size) __allowed(on_parameter) +#define __deref_opt_in_xcount(size) __allowed(on_parameter) +#define __deref_opt_out __allowed(on_parameter) +#define __deref_opt_out_ecount(size) __allowed(on_parameter) +#define __deref_opt_out_bcount(size) __allowed(on_parameter) +#define __deref_opt_out_xcount(size) __allowed(on_parameter) +#define __deref_opt_out_ecount_part(size,len) __allowed(on_parameter) +#define __deref_opt_out_bcount_part(size,len) __allowed(on_parameter) +#define __deref_opt_out_xcount_part(size,len) __allowed(on_parameter) +#define __deref_opt_out_ecount_full(size) __allowed(on_parameter) +#define __deref_opt_out_bcount_full(size) __allowed(on_parameter) +#define __deref_opt_out_xcount_full(size) __allowed(on_parameter) +#define __deref_opt_inout __allowed(on_parameter) +#define __deref_opt_inout_ecount(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount(size) __allowed(on_parameter) +#define __deref_opt_inout_xcount(size) __allowed(on_parameter) +#define __deref_opt_inout_ecount_part(size,len) __allowed(on_parameter) +#define __deref_opt_inout_bcount_part(size,len) __allowed(on_parameter) +#define __deref_opt_inout_xcount_part(size,len) __allowed(on_parameter) +#define __deref_opt_inout_ecount_full(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_full(size) __allowed(on_parameter) +#define __deref_opt_inout_xcount_full(size) __allowed(on_parameter) +#define __deref_opt_inout_z __allowed(on_parameter) +#define __deref_opt_inout_ecount_z(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_z(size) __allowed(on_parameter) +#define __deref_opt_ecount_opt(size) __allowed(on_parameter) +#define __deref_opt_bcount_opt(size) __allowed(on_parameter) +#define __deref_opt_xcount_opt(size) __allowed(on_parameter) +#define __deref_opt_in_opt __allowed(on_parameter) +#define __deref_opt_in_ecount_opt(size) __allowed(on_parameter) +#define __deref_opt_in_bcount_opt(size) __allowed(on_parameter) +#define __deref_opt_in_xcount_opt(size) __allowed(on_parameter) +#define __deref_opt_out_opt __allowed(on_parameter) +#define __deref_opt_out_ecount_opt(size) __allowed(on_parameter) +#define __deref_opt_out_bcount_opt(size) __allowed(on_parameter) +#define __deref_opt_out_xcount_opt(size) __allowed(on_parameter) +#define __deref_opt_out_ecount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_out_bcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_out_xcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_out_ecount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_out_bcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_out_xcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_out_z_opt __allowed(on_parameter) +#define __deref_opt_out_ecount_z_opt(size) __allowed(on_parameter) +#define __deref_opt_out_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_opt __allowed(on_parameter) +#define __deref_opt_inout_ecount_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_xcount_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_ecount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_inout_bcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_inout_xcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_inout_ecount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_xcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_z_opt __allowed(on_parameter) +#define __deref_opt_inout_ecount_z_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_z_opt(size) __allowed(on_parameter) +/************************************************************************ +* Advanced Annotations +* +* Advanced annotations describe behavior that is not expressible with the +* regular buffer macros. These may be used either to annotate buffer +* parameters that involve complex or conditional behavior, or to enrich +* existing annotations with additional information. +* +* __success(expr) T f() : indicates whether function f succeeded or +* not. If is true at exit, all the function's guarantees (as given +* by other annotations) must hold. If is false at exit, the caller +* should not expect any of the function's guarantees to hold. If not used, +* the function must always satisfy its guarantees. Added automatically to +* functions that indicate success in standard ways, such as by returning an +* HRESULT. +* +* __out_awcount(expr, size) T *p : Pointer p is a buffer whose size may be +* given in either bytes or elements. If is true, this acts like +* __out_bcount. If is false, this acts like __out_ecount. This +* should only be used to annotate old APIs. +* +* __in_awcount(expr, size) T* p : Pointer p is a buffer whose size may be given +* in either bytes or elements. If is true, this acts like +* __in_bcount. If is false, this acts like __in_ecount. This should +* only be used to annotate old APIs. +* +* __nullterminated T* p : Pointer p is a buffer that may be read or written +* up to and including the first '\0' character or pointer. May be used on +* typedefs, which marks valid (properly initialized) instances of that type +* as being null-terminated. +* +* __nullnullterminated T* p : Pointer p is a buffer that may be read or +* written up to and including the first sequence of two '\0' characters or +* pointers. May be used on typedefs, which marks valid instances of that +* type as being double-null terminated. +* +* __reserved T v : Value v must be 0/NULL, reserved for future use. +* +* __checkReturn T f(); : Return value of f must not be ignored by callers +* of this function. +* +* __typefix(ctype) T v : Value v should be treated as an instance of ctype, +* rather than its declared type when considering validity. +* +* __override T f(); : Specify C#-style 'override' behaviour for overriding +* virtual methods. +* +* __callback T f(); : Function f can be used as a function pointer. +* +* __format_string T p : Pointer p is a string that contains % markers in +* the style of printf. +* +* __blocksOn(resource) f(); : Function f blocks on the resource 'resource'. +* +* __fallthrough : Annotates switch statement labels where fall-through is +* desired, to distinguish from forgotten break statements. +* +* __range(low_bnd, up_bnd) int f(): The return from the function "f" must +* be in the inclusive numeric range [low_bnd, up_bnd]. +* +* __in_range(low_bnd, up_bnd) int i : Precondition that integer i must be +* in the inclusive numeric range [low_bnd, up_bnd]. +* +* __out_range(low_bnd, up_bnd) int i : Postcondition that integer i must be +* in the inclusive numeric range [low_bnd, up_bnd]. +* +* __deref_in_range(low_bnd, up_bnd) int* pi : Precondition that integer *pi +* must be in the inclusive numeric range [low_bnd, up_bnd]. +* +* __deref_out_range(low_bnd, up_bnd) int* pi : Postcondition that integer +* *pi must be in the inclusive numeric range [low_bnd, up_bnd]. +* +* The first argument of a range macro may also be a C relational operator +* (<,>,!=, ==, <=, >=). +* +* __range(rel_op, j) int f(): Postcondition that "f() rel_op j" must be +* true. Note that j may be a expression known only at runtime. +* +* __in_range(rel_op, j) int i : Precondition that "i rel_op j" must be +* true. Note that j may be a expression known only at runtime. +* +* __out_range(rel_op, j) int i : Postcondition that integer "i rel_op j" +* must be true. Note that j may be a expression known only at runtime. +* +* __deref_in_range(rel_op, j) int *pi : Precondition that "*pi rel_op j" +* must be true. Note that j may be a expression known only at runtime. +* +* __deref_out_range(rel_op, j) int *pi : Postcondition that "*pi rel_op j" +* must be true. Note that j may be a expression known only at runtime. +* +* __in_bound int i : Precondition that integer i must be bound, but the +* exact range can't be specified at compile time. __in_range should be +* used if the range can be explicitly stated. +* +* __out_bound int i : Postcondition that integer i must be bound, but the +* exact range can't be specified at compile time. __out_range should be +* used if the range can be explicitly stated. +* +* __deref_out_bound int pi : Postcondition that integer *pi must be bound, +* but the exact range can't be specified at compile time. +* __deref_out_range should be used if the range can be explicitly stated. +* +* __assume_bound(expr); : Assume that the expression is bound to some known +* range. This can be used to suppress integer overflow warnings on integral +* expressions that are known to be bound due to reasons not explicit in the +* code. Use as a statement in the body of a function. +* +* __allocator void f(): Function allocates memory using an integral size +* argument +* +* ---------------------------------------------------------------------------- +* Advanced Annotation Examples +* +* __success(return == TRUE) LWSTDAPI_(BOOL) +* PathCanonicalizeA(__out_ecount(MAX_PATH) LPSTR pszBuf, LPCSTR pszPath); +* // pszBuf is only guaranteed to be null-terminated when TRUE is returned. +* +* // Initialized LPWSTRs are null-terminated strings. +* typedef __nullterminated WCHAR* LPWSTR; +* +* __out_ecount(cch) __typefix(LPWSTR) void *psz; +* // psz is a buffer parameter which will be a null-terminated WCHAR string +* // at exit, and which initially contains cch WCHARs. +* +************************************************************************/ +#define __success(expr) __allowed(on_function_or_typedecl) +#define __out_awcount(expr,size) __allowed(on_parameter) +#define __in_awcount(expr,size) __allowed(on_parameter) +#define __nullterminated __allowed(on_typedecl) +#define __nullnullterminated __allowed(on_typedecl) +#define __reserved __allowed(on_parameter) +#define __checkReturn __allowed(on_function) +#define __typefix(ctype) __allowed(on_parameter_or_return) +#define __override __allowed(on_function) +#define __callback __allowed(on_function) +#define __format_string __allowed(on_parameter_or_return) +#define __blocksOn(resource) __allowed(on_function) +#define __fallthrough __allowed(as_statement) +#define __range(lb,ub) __allowed(on_return) +#define __in_range(lb,ub) __allowed(on_parameter) +#define __out_range(lb,ub) __allowed(on_parameter) +#define __deref_in_range(lb,ub) __allowed(on_parameter) +#define __deref_out_range(lb,ub) __allowed(on_parameter) +#define __field_range(lb,ub) __allowed(on_field) +#define __bound __allowed(on_return) +#define __in_bound __allowed(on_parameter) +#define __out_bound __allowed(on_parameter) +#define __deref_out_bound __allowed(on_parameter) +#define __assume_bound(i) __allowed(as_statement_with_arg(i)) +#define __allocator __allowed(on_function) +/*************************************************************************** +* Expert Macros +***************************************************************************/ +#define __null __allowed(on_typedecl) +#define __notnull __allowed(on_typedecl) +#define __maybenull __allowed(on_typedecl) +#define __exceptthat __allowed(on_typedecl) +/*************************************************************************** +* Macros to classify fields of structures. +* Structure Annotations +* +* The buffer annotations are a convenient way of describing +* relationships between buffers and their size on a function by +* function basis. Very often struct or class data members have similar +* invariants, which can be expressed directly on the type. +* +* Similar to our buffer annotations we can summarize all the various +* structure annotations by one choosing an element from each column of +* this table to build a composite annotation. +* +* +--------------------------------------------------+ +* | Selector | Units | Size/Init | Optional | +* |----------+---------+------------------+----------| +* | __field | _ecount | (size) | empty | +* |----------+---------+------------------+----------| +* | __struct | _bcount | _full(size) | _opt | +* |----------+---------+------------------+----------| +* | | _xcount | _part(size,init) | | +* +--------------------------------------------------+ +* +* Note that empty represents the empty string. Sometime arguments need +* to be "floated" to the left to give us a valid annotation name. For +* example the naive combination __field_ecount(size)_opt is actually +* written as __field_ecount_opt(size). Not all possible combinations +* are currently supported or sensible. See specstrings_strict.h for +* the currently supported set. Those that are supported are documented +* below. +* +*Summary of Elements +* +* Selector +* +* __field +* The annotation should only be placed in front +* of data members of structures and classes. The +* data members are pointers to a block of data. +* The annotations describe properties about the +* size of the block of data. This can be used for +* +* __struct +* The annotation should only be placed at the +* beginning of the definition of a structure or +* class. These annotations are used when a struct +* or class is used as a "header" that is +* allocated inline with a block of data and there +* is no apparent field that represents the tail +* end of the structure. +* +* Units +* +* _ecount +* All size and initialization values are in terms +* of elements of the appropriate type +* +* _bcount +* All size and initialization values are in terms +* of raw byte sizes. +* +* _xcount +* The size or initialization values cannot be +* properly expressed as a simple byte or element +* count, and instead a place holder is used to +* document the relationship. +* +* Size/Init +* All the size/init expressions can contain references to +* other fields in the struct or class. +* +* (size) +* The size of the buffer is determined by the +* expression size. Unless, the type of the buffer +* provides more information nothing is know about +* how much of this data is initialized. For +* example, if the data member happens to be a +* string type such as LPSTR. It is assumed that +* the data is initialized to the first '\0'. +* +* _full(size) +* The size of the buffer is determined by the +* expression size and all the data in the buffer +* is guaranteed to be initialized. +* +* _part(size,init) +* The size of the buffer is determined by the +* expression size and all the data in the buffer +* is guaranteed to be initialized up to init +* elements or bytes. +* +* Optional +* +* empty +* The pointer to the block of memory is never +* NULL +* +* _opt +* The pointer to the block of memory is may be +* NULL +* +* +* // Basic Usage of Struct Annotations +* #include +* #include +* struct buf_s { +* int sz; +* __field_bcount_full(sz) +* char *buf; +* }; +* void InitBuf(__out struct *buf_s b,int sz) { +* b->buf = calloc(sz,sizeof(char)); +* b->sz = sz; +* } +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(b->buf,b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(b->buf,b->sz,sizeof(char),fp); +* } +* +* +* +* // Inline Allocated Buffer +* struct buf_s { +* int sz; +* __field_bcount(sz) +* char buf[1]; +* }; +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(&(b->buf),b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(&(b->buf),b->sz,sizeof(char),fp); +* } +* +* +* +* // Embedded Header Structure +* __struct_bcount(sz) +* struct buf_s { +* int sz; +* }; +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(&b,b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(&b,b->sz,sizeof(char),fp); +* } +* +* +****************************************************************************/ +#define __field_ecount(size) __allowed(on_field) +#define __field_bcount(size) __allowed(on_field) +#define __field_xcount(size) __allowed(on_field) +#define __field_ecount_opt(size) __allowed(on_field) +#define __field_bcount_opt(size) __allowed(on_field) +#define __field_xcount_opt(size) __allowed(on_field) +#define __field_ecount_part(size,init) __allowed(on_field) +#define __field_bcount_part(size,init) __allowed(on_field) +#define __field_xcount_part(size,init) __allowed(on_field) +#define __field_ecount_part_opt(size,init) __allowed(on_field) +#define __field_bcount_part_opt(size,init) __allowed(on_field) +#define __field_xcount_part_opt(size,init) __allowed(on_field) +#define __field_ecount_full(size) __allowed(on_field) +#define __field_bcount_full(size) __allowed(on_field) +#define __field_xcount_full(size) __allowed(on_field) +#define __field_ecount_full_opt(size) __allowed(on_field) +#define __field_bcount_full_opt(size) __allowed(on_field) +#define __field_xcount_full_opt(size) __allowed(on_field) +#define __struct_bcount(size) __allowed(on_struct) +#define __struct_xcount(size) __allowed(on_struct) + +/*************************************************************************** +* Macros to classify the entrypoints and indicate their category. +* +* Pre-defined control point categories include: RPC, KERNEL, GDI. +* +* Pre-defined control point macros include: +* __rpc_entry, __kernel_entry, __gdi_entry. +***************************************************************************/ +#define __control_entrypoint(category) __allowed(on_function) +#define __rpc_entry __allowed(on_function) +#define __kernel_entry __allowed(on_function) +#define __gdi_entry __allowed(on_function) + +/*************************************************************************** +* Macros to track untrusted data and their validation. The list of untrusted +* sources include: +* +* FILE - File reading stream or API +* NETWORK - Socket readers +* INTERNET - WinInet and WinHttp readers +* USER_REGISTRY - HKCU portions of the registry +* USER_MODE - Parameters to kernel entry points +* RPC - Parameters to RPC entry points +* DRIVER - Device driver +***************************************************************************/ +#define __in_data_source(src_sym) __allowed(on_parameter) +#define __out_data_source(src_sym) __allowed(on_parameter) +#define __field_data_source(src_sym) __allowed(on_field) +#define __this_out_data_source(src_syn) __allowed(on_function) + +/************************************************************************** +* Macros to tag file parsing code. Predefined formats include: +* PNG - Portable Network Graphics +* JPEG - Joint Photographic Experts Group +* BMP - Bitmap +* RC_BMP - Resource bitmap +* WMF - Windows Metafile +* EMF - Windows Enhanced Metafile +* GIF - Graphics Interchange Format +* MIME_TYPE - MIME type from header tokens +* MAIL_MONIKER - MAIL information refered by URL moniker +* HTML - HyperText Markup Language +* WMPHOTO - Windows media photo +* OE_VCARD - Outlook Express virtual card +* OE_CONTACT - Outlook Express contact +* MIDI - Musical Instrument Digital Interface +* LDIF - LDAP Data Interchange Format +* AVI - Audio Visual Interchange +* ACM - Audio Compression Manager +**************************************************************************/ +#define __out_validated(filetype_sym) __allowed(on_parameter) +#define __this_out_validated(filetype_sym) __allowed(on_function) +#define __file_parser(filetype_sym) __allowed(on_function) +#define __file_parser_class(filetype_sym) __allowed(on_struct) +#define __file_parser_library(filetype_sym) __allowed(as_global_decl) + +/*************************************************************************** +* Macros to track the code content in the file. The type of code +* contents currently tracked: +* +* NDIS_DRIVER - NDIS Device driver +***************************************************************************/ +#define __source_code_content(codetype_sym) __allowed(as_global_decl) + +/*************************************************************************** +* Macros to track the code content in the class. The type of code +* contents currently tracked: +* +* DCOM - Class implementing DCOM +***************************************************************************/ +#define __class_code_content(codetype_sym) __allowed(on_struct) + +/************************************************************************* +* Macros to tag encoded function pointers +**************************************************************************/ +#define __encoded_pointer +#define __encoded_array +#define __field_encoded_pointer __allowed(on_field) +#define __field_encoded_array __allowed(on_field) + +#define __transfer(formal) __allowed(on_parameter_or_return) +#define __assume_validated(exp) __allowed(as_statement_with_arg(exp)) + +/************************************************************************* +* __analysis_assume(expr) : Expert macro use only when directed. Use this to +* tell static analysis tools like PREfix and PREfast about a non-coded +* assumption that you wish the tools to assume. The assumption will be +* understood by those tools. By default there is no dynamic checking or +* static checking of the assumption in any build. +* +* To obtain dynamic checking wrap this macro in your local version of a debug +* assert. +* Please do not put function calls in the expression because this is not +* supported by all tools: +* __analysis_assume(GetObject () != NULL); // DO NOT DO THIS +* +*************************************************************************/ +#define __analysis_assume(expr) __allowed(as_statement_with_arg(expr)) +#define __analysis_assert(expr) __allowed(as_statement_with_arg(expr)) + +/************************************************************************* +* __analysis_hint(hint_sym) : Expert macro use only when +* directed. Use this to influence certain analysis heuristics +* used by the tools. These hints do not describe the semantics +* of functions but simply direct the tools to act in a certain +* way. +* +* Current hints that are supported are: +* +* INLINE - inline this function during analysis overrides any +* default heuristics +* NOINLINE - do not inline this function during analysis overrides +* and default heuristics +*************************************************************************/ +#define __analysis_hint(hint) __allowed(on_function) + +/************************************************************************* +* Macros to encode abstract properties of values. Used by SALadt.h +*************************************************************************/ +#define __type_has_adt_prop(adt,prop) __allowed(on_typdecl) +#define __out_has_adt_prop(adt,prop) __allowed(on_parameter) +#define __out_not_has_adt_prop(adt,prop) __allowed(on_parameter) +#define __out_transfer_adt_prop(arg) __allowed(on_parameter) +#define __out_has_type_adt_props(typ) __allowed(on_parameter) +#define __assume_ValidCompNameA(expr) __allowed(as_statement_with_arg(expr)) +#define __assume_ValidCompNameW(expr) __allowed(as_statement_with_arg(expr)) + +/************************************************************************* +* Macros used by Prefast for Drivers +* +* __possibly_notnulltermiated : +* +* Used for return values of parameters or functions that do not +* guarantee nullterimination in all cases. +* +*************************************************************************/ +#define __possibly_notnulltermiated __allowed(on_parameter_or_return) + +/************************************************************************* +* Advanced macros +* +* __volatile +* The __volatile annotation identifies a global variable or +* structure field that: +* 1) is not declared volatile; +* 2) is accessed concurrently by multiple threads. +* +* The __deref_volatile annotation identifies a global variable +* or structure field that stores a pointer to some data that: +* 1) is not declared volatile; +* 2) is accessed concurrently by multiple threads. +* +* Prefast uses these annotations to find patterns of code that +* may result in unexpected re-fetching of the global variable +* into a local variable. +* +* We also provide two complimentary annotations __nonvolatile +* and __deref_nonvolatile that could be used to suppress Prefast +* +* re-fetching warnings on variables that are known either: +* 1) not to be in danger of being re-fetched or, +* 2) not to lead to incorrect results if they are re-fetched +* +*************************************************************************/ +#define __volatile __allowed(on_global_or_field) +#define __deref_volatile __allowed(on_global_or_field) +#define __nonvolatile __allowed(on_global_or_field) +#define __deref_nonvolatile __allowed(on_global_or_field) + +/************************************************************************* +* Macros deprecated with strict level greater then 1. +**************************************************************************/ +#if (__SPECSTRINGS_STRICT_LEVEL > 1) +/* Must come before macro defintions */ +#pragma deprecated(__in_nz) +#pragma deprecated(__in_ecount_nz) +#pragma deprecated(__in_bcount_nz) +#pragma deprecated(__out_nz) +#pragma deprecated(__out_nz_opt) +#pragma deprecated(__out_ecount_nz) +#pragma deprecated(__out_bcount_nz) +#pragma deprecated(__inout_nz) +#pragma deprecated(__inout_ecount_nz) +#pragma deprecated(__inout_bcount_nz) +#pragma deprecated(__in_nz_opt) +#pragma deprecated(__in_ecount_nz_opt) +#pragma deprecated(__in_bcount_nz_opt) +#pragma deprecated(__out_ecount_nz_opt) +#pragma deprecated(__out_bcount_nz_opt) +#pragma deprecated(__inout_nz_opt) +#pragma deprecated(__inout_ecount_nz_opt) +#pragma deprecated(__inout_bcount_nz_opt) +#pragma deprecated(__deref_out_nz) +#pragma deprecated(__deref_out_ecount_nz) +#pragma deprecated(__deref_out_bcount_nz) +#pragma deprecated(__deref_inout_nz) +#pragma deprecated(__deref_inout_ecount_nz) +#pragma deprecated(__deref_inout_bcount_nz) +#pragma deprecated(__deref_out_nz_opt) +#pragma deprecated(__deref_out_ecount_nz_opt) +#pragma deprecated(__deref_out_bcount_nz_opt) +#pragma deprecated(__deref_inout_nz_opt) +#pragma deprecated(__deref_inout_ecount_nz_opt) +#pragma deprecated(__deref_inout_bcount_nz_opt) +#pragma deprecated(__deref_opt_inout_nz) +#pragma deprecated(__deref_opt_inout_ecount_nz) +#pragma deprecated(__deref_opt_inout_bcount_nz) +#pragma deprecated(__deref_opt_out_nz_opt) +#pragma deprecated(__deref_opt_out_ecount_nz_opt) +#pragma deprecated(__deref_opt_out_bcount_nz_opt) +#pragma deprecated(__deref_opt_inout_nz_opt) +#pragma deprecated(__deref_opt_inout_ecount_nz_opt) +#pragma deprecated(__deref_opt_inout_bcount_nz_opt) +#pragma deprecated(__deref) +#pragma deprecated(__pre) +#pragma deprecated(__post) +#pragma deprecated(__readableTo) +#pragma deprecated(__writableTo) +#pragma deprecated(__maybevalid) +#pragma deprecated(__data_entrypoint) +#pragma deprecated(__inexpressible_readableTo) +#pragma deprecated(__readonly) +#pragma deprecated(__byte_writableTo) +#pragma deprecated(__byte_readableTo) +#pragma deprecated(__elem_readableTo) +#pragma deprecated(__elem_writableTo) +#pragma deprecated(__valid) +#pragma deprecated(__notvalid) +#pragma deprecated(__refparam) +#pragma deprecated(__precond) +#endif +/* Define soon to be deprecated macros to nops. */ +#define __in_nz +#define __in_ecount_nz(size) +#define __in_bcount_nz(size) +#define __out_nz +#define __out_nz_opt +#define __out_ecount_nz(size) +#define __out_bcount_nz(size) +#define __inout_nz +#define __inout_ecount_nz(size) +#define __inout_bcount_nz(size) +#define __in_nz_opt +#define __in_ecount_nz_opt(size) +#define __in_bcount_nz_opt(size) +#define __out_ecount_nz_opt(size) +#define __out_bcount_nz_opt(size) +#define __inout_nz_opt +#define __inout_ecount_nz_opt(size) +#define __inout_bcount_nz_opt(size) +#define __deref_out_nz +#define __deref_out_ecount_nz(size) +#define __deref_out_bcount_nz(size) +#define __deref_inout_nz +#define __deref_inout_ecount_nz(size) +#define __deref_inout_bcount_nz(size) +#define __deref_out_nz_opt +#define __deref_out_ecount_nz_opt(size) +#define __deref_out_bcount_nz_opt(size) +#define __deref_inout_nz_opt +#define __deref_inout_ecount_nz_opt(size) +#define __deref_inout_bcount_nz_opt(size) +#define __deref_opt_inout_nz +#define __deref_opt_inout_ecount_nz(size) +#define __deref_opt_inout_bcount_nz(size) +#define __deref_opt_out_nz_opt +#define __deref_opt_out_ecount_nz_opt(size) +#define __deref_opt_out_bcount_nz_opt(size) +#define __deref_opt_inout_nz_opt +#define __deref_opt_inout_ecount_nz_opt(size) +#define __deref_opt_inout_bcount_nz_opt(size) +#define __deref +#define __pre +#define __post +#define __readableTo(count) +#define __writableTo(count) +#define __maybevalid +#define __inexpressible_readableTo(string) +#define __data_entrypoint(category) +#define __readonly +#define __byte_writableTo(count) +#define __byte_readableTo(count) +#define __elem_readableTo(count) +#define __elem_writableTo(count) +#define __valid +#define __notvalid +#define __refparam +#define __precond(condition) + +/************************************************************************* +* Definitions to force a compile error when macros are used improperly. +* Relies on VS 2005 source annotations. +*************************************************************************/ +#define __allowed(p) __$allowed_##p +#define __$allowed_as_global_decl /* empty */ +#define __$allowed_as_statement_with_arg(x) \ + __pragma(warning(push)) __pragma(warning(disable : 4548)) \ + do {__noop(x);} while((0,0) __pragma(warning(pop)) ) +#define __$allowed_as_statement __$allowed_as_statement_with_arg(1) + +/************************************************************************** +* This should go away. It's only for __success which we should split into. +* __success and __typdecl_sucess +***************************************************************************/ +#define __$allowed_on_function_or_typedecl /* empty */ +#if (__SPECSTRINGS_STRICT_LEVEL == 1) || (__SPECSTRINGS_STRICT_LEVEL == 2) +#define __$allowed_on_typedecl /* empty */ +#define __$allowed_on_return /* empty */ +#define __$allowed_on_parameter /* empty */ +#define __$allowed_on_function /* empty */ +#define __$allowed_on_struct /* empty */ +#define __$allowed_on_field /* empty */ +#define __$allowed_on_parameter_or_return /* empty */ +#define __$allowed_on_global_or_field /* empty */ +#elif __SPECSTRINGS_STRICT_LEVEL == 3 +#define __$allowed_on_typedecl /* empty */ +/* Define dummy source attributes. Still needs more testing */ +#define __$allowed_on_return [returnvalue: OnReturnOnly] +#define __$allowed_on_parameter [OnParameterOnly] +#define __$allowed_on_function [method: OnFunctionOnly] +#define __$allowed_on_struct [OnStructOnly] +#define __$allowed_on_field [OnFieldOnly] +#define __$allowed_on_parameter_or_return [OnParameterOrReturnOnly] +#define __$allowed_on_global_or_field /* empty */ +#pragma push_macro( "DECL_SA" ) +#pragma push_macro( "SA" ) +#ifdef __cplusplus +#define SA(x) x +#define DECL_SA(name,loc) \ + [repeatable] \ + [source_annotation_attribute( loc )] \ + struct name##Attribute { name##Attribute(); const char* ignored; }; +#else +#define SA(x) SA_##x +#define DECL_SA(name,loc) \ + [source_annotation_attribute( loc )] \ + struct name { const char* ignored; };\ + typedef struct name name; +#endif /* #endif __cplusplus */ +DECL_SA(OnParameterOnly,SA(Parameter)); +DECL_SA(OnReturnOnly,SA(ReturnValue)); +DECL_SA(OnFunctionOnly,SA(Method)); +DECL_SA(OnStructOnly,SA(Struct)); +DECL_SA(OnFieldOnly,SA(Field)); +DECL_SA(OnParameterOrReturnOnly,SA(Parameter) | SA(ReturnValue)); +#pragma pop_macro( "SA" ) +#pragma pop_macro( "DECL_SA" ) +#endif +#endif + + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_undef.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_undef.h new file mode 100644 index 0000000..ed53c31 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/common/include/wmspecstrings_undef.h @@ -0,0 +1,406 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + + +#undef __$adt_add_prop +#undef __$adt_prop +#undef __$adt_remove_prop +#undef __$adt_transfer_prop +#undef __$adt_type_props +#undef __$nonvolatile +#undef __$possibly_notnulltermiated +#undef __$volatile +#undef __allocator +#undef __analysis_assert +#undef __analysis_assume +#undef __analysis_hint +#undef __assume_ValidCompNameA +#undef __assume_ValidCompNameW +#undef __assume_bound +#undef __assume_validated +#undef __bcount +#undef __bcount_opt +#undef __blocksOn +#undef __bound +#undef __byte_readableTo +#undef __byte_writableTo +#undef __callback +#undef __checkReturn +#undef __class_code_content +#undef __control_entrypoint +#undef __data_entrypoint +#undef __deref +#undef __deref_bcount +#undef __deref_bcount_opt +#undef __deref_ecount +#undef __deref_ecount_opt +#undef __deref_in +#undef __deref_in_bcount +#undef __deref_in_bcount_opt +#undef __deref_in_ecount +#undef __deref_in_ecount_opt +#undef __deref_in_opt +#undef __deref_in_range +#undef __deref_in_xcount +#undef __deref_in_xcount_opt +#undef __deref_inout +#undef __deref_inout_bcount +#undef __deref_inout_bcount_full +#undef __deref_inout_bcount_full_opt +#undef __deref_inout_bcount_nz +#undef __deref_inout_bcount_nz_opt +#undef __deref_inout_bcount_opt +#undef __deref_inout_bcount_part +#undef __deref_inout_bcount_part_opt +#undef __deref_inout_bcount_z +#undef __deref_inout_bcount_z_opt +#undef __deref_inout_ecount +#undef __deref_inout_ecount_full +#undef __deref_inout_ecount_full_opt +#undef __deref_inout_ecount_nz +#undef __deref_inout_ecount_nz_opt +#undef __deref_inout_ecount_opt +#undef __deref_inout_ecount_part +#undef __deref_inout_ecount_part_opt +#undef __deref_inout_ecount_z +#undef __deref_inout_ecount_z_opt +#undef __deref_inout_nz +#undef __deref_inout_nz_opt +#undef __deref_inout_opt +#undef __deref_inout_xcount +#undef __deref_inout_xcount_full +#undef __deref_inout_xcount_full_opt +#undef __deref_inout_xcount_opt +#undef __deref_inout_xcount_part +#undef __deref_inout_xcount_part_opt +#undef __deref_inout_z +#undef __deref_inout_z_opt +#undef __deref_nonvolatile +#undef __deref_opt_bcount +#undef __deref_opt_bcount_opt +#undef __deref_opt_ecount +#undef __deref_opt_ecount_opt +#undef __deref_opt_in +#undef __deref_opt_in_bcount +#undef __deref_opt_in_bcount_opt +#undef __deref_opt_in_ecount +#undef __deref_opt_in_ecount_opt +#undef __deref_opt_in_opt +#undef __deref_opt_in_xcount +#undef __deref_opt_in_xcount_opt +#undef __deref_opt_inout +#undef __deref_opt_inout_bcount +#undef __deref_opt_inout_bcount_full +#undef __deref_opt_inout_bcount_full_opt +#undef __deref_opt_inout_bcount_nz +#undef __deref_opt_inout_bcount_nz_opt +#undef __deref_opt_inout_bcount_opt +#undef __deref_opt_inout_bcount_part +#undef __deref_opt_inout_bcount_part_opt +#undef __deref_opt_inout_bcount_z +#undef __deref_opt_inout_bcount_z_opt +#undef __deref_opt_inout_ecount +#undef __deref_opt_inout_ecount_full +#undef __deref_opt_inout_ecount_full_opt +#undef __deref_opt_inout_ecount_nz +#undef __deref_opt_inout_ecount_nz_opt +#undef __deref_opt_inout_ecount_opt +#undef __deref_opt_inout_ecount_part +#undef __deref_opt_inout_ecount_part_opt +#undef __deref_opt_inout_ecount_z +#undef __deref_opt_inout_ecount_z_opt +#undef __deref_opt_inout_nz +#undef __deref_opt_inout_nz_opt +#undef __deref_opt_inout_opt +#undef __deref_opt_inout_xcount +#undef __deref_opt_inout_xcount_full +#undef __deref_opt_inout_xcount_full_opt +#undef __deref_opt_inout_xcount_opt +#undef __deref_opt_inout_xcount_part +#undef __deref_opt_inout_xcount_part_opt +#undef __deref_opt_inout_z +#undef __deref_opt_inout_z_opt +#undef __deref_opt_out +#undef __deref_opt_out_bcount +#undef __deref_opt_out_bcount_full +#undef __deref_opt_out_bcount_full_opt +#undef __deref_opt_out_bcount_nz_opt +#undef __deref_opt_out_bcount_opt +#undef __deref_opt_out_bcount_part +#undef __deref_opt_out_bcount_part_opt +#undef __deref_opt_out_bcount_z_opt +#undef __deref_opt_out_ecount +#undef __deref_opt_out_ecount_full +#undef __deref_opt_out_ecount_full_opt +#undef __deref_opt_out_ecount_nz_opt +#undef __deref_opt_out_ecount_opt +#undef __deref_opt_out_ecount_part +#undef __deref_opt_out_ecount_part_opt +#undef __deref_opt_out_ecount_z_opt +#undef __deref_opt_out_nz_opt +#undef __deref_opt_out_opt +#undef __deref_opt_out_xcount +#undef __deref_opt_out_xcount_full +#undef __deref_opt_out_xcount_full_opt +#undef __deref_opt_out_xcount_opt +#undef __deref_opt_out_xcount_part +#undef __deref_opt_out_xcount_part_opt +#undef __deref_opt_out_z_opt +#undef __deref_opt_xcount +#undef __deref_opt_xcount_opt +#undef __deref_out +#undef __deref_out_bcount +#undef __deref_out_bcount_full +#undef __deref_out_bcount_full_opt +#undef __deref_out_bcount_nz +#undef __deref_out_bcount_nz_opt +#undef __deref_out_bcount_opt +#undef __deref_out_bcount_part +#undef __deref_out_bcount_part_opt +#undef __deref_out_bcount_z +#undef __deref_out_bcount_z_opt +#undef __deref_out_bound +#undef __deref_out_ecount +#undef __deref_out_ecount_full +#undef __deref_out_ecount_full_opt +#undef __deref_out_ecount_nz +#undef __deref_out_ecount_nz_opt +#undef __deref_out_ecount_opt +#undef __deref_out_ecount_part +#undef __deref_out_ecount_part_opt +#undef __deref_out_ecount_z +#undef __deref_out_ecount_z_opt +#undef __deref_out_nz +#undef __deref_out_nz_opt +#undef __deref_out_opt +#undef __deref_out_range +#undef __deref_out_range +#undef __deref_out_xcount +#undef __deref_out_xcount +#undef __deref_out_xcount_full +#undef __deref_out_xcount_full_opt +#undef __deref_out_xcount_opt +#undef __deref_out_xcount_part +#undef __deref_out_xcount_part_opt +#undef __deref_out_z +#undef __deref_out_z_opt +#undef __deref_volatile +#undef __deref_xcount +#undef __deref_xcount_opt +#undef __ecount +#undef __ecount_opt +#undef __elem_readableTo +#undef __elem_writableTo +#undef __encoded_array +#undef __encoded_pointer +#undef __exceptthat +#undef __fallthrough +#undef __field_bcount +#undef __field_bcount_full +#undef __field_bcount_full_opt +#undef __field_bcount_opt +#undef __field_bcount_part +#undef __field_bcount_part_opt +#undef __field_data_source +#undef __field_ecount +#undef __field_ecount_full +#undef __field_ecount_full_opt +#undef __field_ecount_opt +#undef __field_ecount_part +#undef __field_ecount_part_opt +#undef __field_encoded_array +#undef __field_encoded_pointer +#undef __field_range +#undef __field_xcount +#undef __field_xcount_full +#undef __field_xcount_full_opt +#undef __field_xcount_opt +#undef __field_xcount_part +#undef __field_xcount_part_opt +#undef __file_parser +#undef __file_parser_class +#undef __file_parser_library +#undef __format_string +#undef __format_string +#undef __gdi_entry +#undef __in +#undef __in_awcount +#undef __in_bcount +#undef __in_bcount_nz +#undef __in_bcount_nz_opt +#undef __in_bcount_opt +#undef __in_bcount_z +#undef __in_bcount_z_opt +#undef __in_bound +#undef __in_data_source +#undef __in_ecount +#undef __in_ecount_nz +#undef __in_ecount_nz_opt +#undef __in_ecount_opt +#undef __in_ecount_z +#undef __in_ecount_z_opt +#undef __in_nz +#undef __in_nz_opt +#undef __in_opt +#undef __in_range +#undef __in_xcount +#undef __in_xcount_opt +#undef __in_z +#undef __in_z_opt +#undef __inexpressible_readableTo +#undef __inexpressible_writableTo +#undef __inner_assume_bound +#undef __inner_assume_bound_dec +#undef __inner_assume_validated +#undef __inner_assume_validated_dec +#undef __inner_blocksOn +#undef __inner_bound +#undef __inner_callback +#undef __inner_checkReturn +#undef __inner_control_entrypoint +#undef __inner_data_entrypoint +#undef __inner_data_source +#undef __inner_encoded +#undef __inner_fallthrough +#undef __inner_fallthrough_dec +#undef __inner_out_validated +#undef __inner_override +#undef __inner_range +#undef __inner_success +#undef __inner_transfer +#undef __inner_typefix +#undef __inout +#undef __inout_bcount +#undef __inout_bcount_full +#undef __inout_bcount_full_opt +#undef __inout_bcount_nz +#undef __inout_bcount_nz_opt +#undef __inout_bcount_opt +#undef __inout_bcount_part +#undef __inout_bcount_part_opt +#undef __inout_bcount_z +#undef __inout_bcount_z_opt +#undef __inout_ecount +#undef __inout_ecount_full +#undef __inout_ecount_full_opt +#undef __inout_ecount_nz +#undef __inout_ecount_nz_opt +#undef __inout_ecount_opt +#undef __inout_ecount_part +#undef __inout_ecount_part_opt +#undef __inout_ecount_z +#undef __inout_ecount_z_opt +#undef __inout_ecount_z_opt +#undef __inout_nz +#undef __inout_nz_opt +#undef __inout_opt +#undef __inout_xcount +#undef __inout_xcount_full +#undef __inout_xcount_full_opt +#undef __inout_xcount_opt +#undef __inout_xcount_part +#undef __inout_xcount_part_opt +#undef __inout_z +#undef __inout_z_opt +#undef __kernel_entry +#undef __maybenull +#undef __maybereadonly +#undef __maybevalid +#undef __nonvolatile +#undef __notnull +#undef __notreadonly +#undef __notvalid +#undef __null +#undef __nullnullterminated +#undef __nullterminated +#undef __out +#undef __out_awcount +#undef __out_bcount +#undef __out_bcount_full +#undef __out_bcount_full_opt +#undef __out_bcount_nz +#undef __out_bcount_nz_opt +#undef __out_bcount_opt +#undef __out_bcount_part +#undef __out_bcount_part_opt +#undef __out_bcount_z +#undef __out_bcount_z_opt +#undef __out_bound +#undef __out_data_source +#undef __out_ecount +#undef __out_ecount_full +#undef __out_ecount_full_opt +#undef __out_ecount_nz +#undef __out_ecount_nz_opt +#undef __out_ecount_opt +#undef __out_ecount_part +#undef __out_ecount_part_opt +#undef __out_ecount_z +#undef __out_ecount_z_opt +#undef __out_has_adt_prop +#undef __out_has_type_adt_props +#undef __out_not_has_adt_prop +#undef __out_nz +#undef __out_nz_opt +#undef __out_opt +#undef __out_range +#undef __out_transfer_adt_prop +#undef __out_validated +#undef __out_xcount +#undef __out_xcount_full +#undef __out_xcount_full_opt +#undef __out_xcount_opt +#undef __out_xcount_part +#undef __out_xcount_part_opt +#undef __out_z +#undef __override +#undef __possibly_notnulltermiated +#undef __post +#undef __postcond +#undef __pre +#undef __precond +#undef __range +#undef __readableTo +#undef __readonly +#undef __refparam +#undef __reserved +#undef __rpc_entry +#undef __source_code_content +#undef __struct_bcount +#undef __struct_xcount +#undef __success +#undef __this_out_data_source +#undef __this_out_validated +#undef __transfer +#undef __type_has_adt_prop +#undef __typefix +#undef __valid +#undef __volatile +#undef __writableTo +#undef __xcount +#undef __xcount_opt \ No newline at end of file diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/doc/JPEGXR_DPK_Spec_1.0.doc b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/doc/JPEGXR_DPK_Spec_1.0.doc new file mode 100644 index 0000000..a5dc1d1 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/doc/JPEGXR_DPK_Spec_1.0.doc differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/doc/readme.txt b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/doc/readme.txt new file mode 100644 index 0000000..e4c9047 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/doc/readme.txt @@ -0,0 +1,100 @@ +JPEG XR Device Porting Kit v1.0 - April 2013 +--------------------------------------------------------------------------------- + +JPEG XR +------- +This device porting kit (DPK) supports the JPEG XR still image format, based on +technology originally developed by Mirosoft under the name HD Photo (formerly +Windows Mediaâ„¢ Photo). The JPEG XR format is similar, but not identical, to the +HD Photo/Windows Mediaâ„¢ Photo format. + +The JPEG XR format replaces the HD Photo/Windows Mediaâ„¢ Photo format in both +Windows 8 and the Windows Image Component (WIC). WIC accompanies the Internet +Explorer 10 redistributable packages for down-level versions of Windows. +Some “Windows Mediaâ„¢ Photo†(WMP) naming conventions are still used internally +with this release of the DPK. + +JPEG XR files use the .jxr extension. Applications that support the JPEG XR +file format should recognize and decode HD Photo/Windows Mediaâ„¢ Photo +.hdp/.wdp files, but only offer to create files with the .jxr extension. + + +Device Porting Kit Contents +--------------------------- +This device porting kit contains documentation, reference source code, sample +applications and utilities for the evaluation and implementation of the JPEG XR +file format and compression technology. + +Assuming the installation dir is C:\jxrlib, all the paths mentioned below are +relative to this base path. + + The Visual Studio 2012 main solution is: + jxrencoderdecoder\JXR_vc11.sln + + Build JXR.sln Debug Configuration, you will get: + jxrencoderdecoder\Debug\JXRDecApp\JXRDecApp.exe + jxrencoderdecoder\Debug\JXREncApp\JXREncApp.exe + +The main directory contains a Unix/Linux compatible make file for building the +encoder and decoder, and associated libraries, including support for big endian +or little endian processor architecture by setting BIG_ENDIAN=1 at build time. +It is the developer's responsibility to properly organize all the source files +according to the paths defined in this make file for its correct operation. +This is provided as a convenience for cross-platform developers and to demonstrate +the correct operation of the encoder and decoder on big endian systems. + +To build static libraries: + + make + +To build shared libraries: + + make SHARED=1 + +The JPEG XR Image Coding Spectification provides a detailed specification of the +compression encoder and decoder algorithms plus the detailed structure of the +compressed data (elementary) bit stream. This document is designed to be used in +conjunction with the included source code. If you find instances where the code +differs from the documentation, the code implementation should be used as the +reference. + +The JPEG XR Image Coding Spectification is an international standard and is +available at: http://www.itu.int/rec/T-REC-T.832 while the reference software is +available at: http://www.itu.int/rec/T-REC-T.835. + +"JPEGXR_DPK_1.0.doc" documents the contents of this porting kit, the usage of +the command line file conversion utilities (JXREncApp.exe and JXRDecApp.exe), and +technical details of the API's and data structures between these sample command +line applications and the core codec. + +The code and documentation in this release represent the final design and +specification of the 1.0 bit stream, and can be used as the reference for final +implementations of encoders and decoders for JPEG XR. + +This release of the DPK has received extensive testing of all the various pixel +formats, encoder options and modes of operation. We are confident that most errors +and other bugs have been resolved. Any code bugs, documentation errors or other +discrepancies found in this release candidate should be reported to Microsoft as +promptly as possible. These can be submitted to hdview@microsoft.com. + +This DPK provides basic support for big endian architectures. We have +successfully tested the encoder and decoder using a big endian processor. This +support is provided as a starting reference to be adapted to the specific +platform and hardware architecture of the target system. + +Contact Information +------------------- +For any and all technical questions or feedback about any part of this Device +Porting Kit, including the documentation, please send email to: + + hdview@microsoft.com + +We will respond as promptly as possible with answers to your questions. + +Additional information, best practices, tools, utilities, sample code, sample +image content, links to additional resources and community discussion can +currently be found at http://hdview.wordpress.com/. + + - The Microsoft JPEG XR Development Team + +--------------------------------------------------------------------------------- diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/JXRTranscode.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/JXRTranscode.c new file mode 100644 index 0000000..f2ed380 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/JXRTranscode.c @@ -0,0 +1,991 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "windowsmediaphoto.h" +#include "strcodec.h" +#include "decode.h" + +EXTERN_C Void freePredInfo(CWMImageStrCodec *); + +EXTERN_C Int ReadWMIHeader(CWMImageInfo *, CWMIStrCodecParam *, CCoreParameters *); +EXTERN_C Int StrIODecInit(CWMImageStrCodec *); +EXTERN_C Int StrDecInit(CWMImageStrCodec *); +EXTERN_C Int readPackets(CWMImageStrCodec *); +EXTERN_C Int DecodeMacroblockDC(CWMImageStrCodec *, CCodingContext *, Int, Int); +EXTERN_C Int DecodeMacroblockLowpass(CWMImageStrCodec *, CCodingContext *, Int, Int); +EXTERN_C Int DecodeMacroblockHighpass(CWMImageStrCodec *, CCodingContext *, Int, Int); +EXTERN_C Void predDCACDec(CWMImageStrCodec *); +EXTERN_C Void predACDec(CWMImageStrCodec *); +EXTERN_C Int StrIODecTerm(CWMImageStrCodec *); +EXTERN_C Void FreeCodingContextDec(CWMImageStrCodec *); + +EXTERN_C Int StrEncInit(CWMImageStrCodec *); +EXTERN_C Int StrIOEncTerm(CWMImageStrCodec *); +EXTERN_C Void FreeCodingContextEnc(CWMImageStrCodec *); +EXTERN_C Int encodeMB(CWMImageStrCodec *, Int, Int); +EXTERN_C Int writeIndexTableNull(CWMImageStrCodec *); +EXTERN_C Void writePacketHeader(BitIOInfo *, U8, U8); + +EXTERN_C Int WriteWMIHeader(CWMImageStrCodec *); +EXTERN_C Int ReadImagePlaneHeader(CWMImageInfo *, CWMIStrCodecParam *, CCoreParameters *, SimpleBitIO *); +EXTERN_C Int WriteImagePlaneHeader(CWMImageStrCodec *); +EXTERN_C Int writeIndexTable(CWMImageStrCodec *); +EXTERN_C Int copyTo(struct WMPStream *, struct WMPStream *, size_t); + +const static Bool bFlipV[O_MAX] = {FALSE, TRUE , FALSE, TRUE, TRUE , TRUE, FALSE, FALSE}; +const static Bool bFlipH[O_MAX] = {FALSE, FALSE, TRUE , TRUE, FALSE, TRUE, FALSE, TRUE}; + +typedef struct CTileQPInfo +{ + U8 dcMode; + U8 dcIndex[MAX_CHANNELS]; + + Bool bUseDC; + U8 lpNum; + Bool bUseDCAlpha; + U8 lpNumAlpha; + U8 lpMode[16]; + U8 lpIndex[16][MAX_CHANNELS]; + + Bool bUseLP; + U8 hpNum; + Bool bUseLPAlpha; + U8 hpNumAlpha; + U8 hpMode[16]; + U8 hpIndex[16][MAX_CHANNELS]; +} CTileQPInfo; + +Void transcodeQuantizer(BitIOInfo * pIO, U8 cIndex[MAX_CHANNELS], U8 cChMode, size_t cChannel) +{ + if(cChMode > 2) + cChMode = 2; + + if(cChannel > 1) + putBit16(pIO, cChMode, 2); // Channel mode + else + cChMode = 0; + + putBit16(pIO, cIndex[0], 8); // Y + + if(cChMode == 1) // MIXED + putBit16(pIO, cIndex[1], 8); // UV + else if(cChMode > 0){ // INDEPENDENT + size_t i; + + for(i = 1; i < cChannel; i ++) + putBit16(pIO, cIndex[i], 8); // UV + } +} + +Void transcodeQuantizers(BitIOInfo * pIO, U8 cIndex[16][MAX_CHANNELS], U8 cChMode[16], U32 cNum, size_t cChannel, Bool bCopy) +{ + putBit16(pIO, bCopy == TRUE ? 1 : 0, 1); + if(bCopy == FALSE){ + U32 i; + + putBit16(pIO, cNum - 1, 4); + + for(i = 0; i < cNum; i ++) + transcodeQuantizer(pIO, cIndex[i], cChMode[i], cChannel); + } +} + +Void transcodeQuantizersAlpha(BitIOInfo * pIO, U8 cIndex[16][MAX_CHANNELS], U32 cNum, size_t iChannel, Bool bCopy) +{ + putBit16(pIO, bCopy == TRUE ? 1 : 0, 1); + if(bCopy == FALSE){ + U32 i; + + putBit16(pIO, cNum - 1, 4); + + for(i = 0; i < cNum; i ++) + putBit16(pIO, cIndex[i][iChannel], 8); + } +} + +Void transcodeTileHeader(CWMImageStrCodec * pSC, CTileQPInfo * pTileQPInfo) +{ + if(pSC->m_bCtxLeft && pSC->m_bCtxTop && pSC->m_bSecondary == FALSE){ // write packet headers + CCodingContext * pContext = &pSC->m_pCodingContext[pSC->cTileColumn]; + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + U8 pID = (U8)((pSC->cTileRow * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + pSC->cTileColumn) & 0x1F); + CWMImageStrCodec * pSCAlpha = (pSC->m_param.bAlphaChannel ? pSC->m_pNextSC : NULL); + const size_t iAlphaPos = pSC->m_param.cNumChannels; + + writePacketHeader(pContext->m_pIODC, pSC->WMISCP.bfBitstreamFormat == SPATIAL ? 0 : 1, pID); + if (pSC->m_param.bTrimFlexbitsFlag && pSC->WMISCP.bfBitstreamFormat == SPATIAL) + putBit16(pContext->m_pIODC, pContext->m_iTrimFlexBits, 4); + + if((pSC->m_param.uQPMode & 1) != 0) // not DC uniform + transcodeQuantizer(pContext->m_pIODC, pTileQPInfo->dcIndex, pTileQPInfo->dcMode, pSC->WMISCP.cChannel); + if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 1) != 0) // not DC uniform + putBit16(pContext->m_pIODC, pTileQPInfo->dcIndex[iAlphaPos], 8); + + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL) { + if(pSC->WMISCP.sbSubband != SB_DC_ONLY){ + if((pSC->m_param.uQPMode & 2) != 0) // not LP uniform + transcodeQuantizers(pContext->m_pIODC, pTileQPInfo->lpIndex, pTileQPInfo->lpMode, pTileQPInfo->lpNum, pSC->WMISCP.cChannel, pTileQPInfo->bUseDC); + if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 2) != 0) // not LP uniform + transcodeQuantizersAlpha(pContext->m_pIODC, pTileQPInfo->lpIndex, pTileQPInfo->lpNumAlpha, iAlphaPos, pTileQPInfo->bUseDCAlpha); + if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){ + if((pSC->m_param.uQPMode & 4) != 0) // not HP uniform + transcodeQuantizers(pContext->m_pIODC, pTileQPInfo->hpIndex, pTileQPInfo->hpMode, pTileQPInfo->hpNum, pSC->WMISCP.cChannel, pTileQPInfo->bUseLP); + if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 4) != 0) // not HP uniform + transcodeQuantizersAlpha(pContext->m_pIODC, pTileQPInfo->hpIndex, pTileQPInfo->hpNumAlpha, iAlphaPos, pTileQPInfo->bUseLPAlpha); + } + } + } + else{ + if(pSC->WMISCP.sbSubband != SB_DC_ONLY){ + writePacketHeader(pContext->m_pIOLP, 2, pID); + if((pSC->m_param.uQPMode & 2) != 0) // not LP uniform + transcodeQuantizers(pContext->m_pIOLP, pTileQPInfo->lpIndex, pTileQPInfo->lpMode, pTileQPInfo->lpNum, pSC->WMISCP.cChannel, pTileQPInfo->bUseDC); + if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 2) != 0) // not LP uniform + transcodeQuantizersAlpha(pContext->m_pIOLP, pTileQPInfo->lpIndex, pTileQPInfo->lpNumAlpha, iAlphaPos, pTileQPInfo->bUseDCAlpha); + + if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){ + writePacketHeader(pContext->m_pIOAC, 3, pID); + if((pSC->m_param.uQPMode & 4) != 0) // not HP uniform + transcodeQuantizers(pContext->m_pIOAC, pTileQPInfo->hpIndex, pTileQPInfo->hpMode, pTileQPInfo->hpNum, pSC->WMISCP.cChannel, pTileQPInfo->bUseLP); + if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 4) != 0) // not HP uniform + transcodeQuantizersAlpha(pContext->m_pIOAC, pTileQPInfo->hpIndex, pTileQPInfo->hpNumAlpha, iAlphaPos, pTileQPInfo->bUseLPAlpha); + + if(pSC->WMISCP.sbSubband != SB_NO_FLEXBITS){ + writePacketHeader(pContext->m_pIOFL, 4, pID); + if (pSC->m_param.bTrimFlexbitsFlag) + putBit16(pContext->m_pIOFL, pContext->m_iTrimFlexBits, 4); + } + } + } + } + pTile->cBitsLP = (pTileQPInfo->bUseDC ? 0 : dquantBits(pTileQPInfo->lpNum)); + pTile->cBitsHP = (pTileQPInfo->bUseLP ? 0 : dquantBits(pTileQPInfo->hpNum)); + if(pSCAlpha != NULL){ + pTile = pSCAlpha->pTile + pSC->cTileColumn; + pTile->cBitsLP = (pTileQPInfo->bUseDCAlpha ? 0 : dquantBits(pTileQPInfo->lpNumAlpha)); + pTile->cBitsHP = (pTileQPInfo->bUseLPAlpha ? 0 : dquantBits(pTileQPInfo->hpNumAlpha)); + } + } +} + +Void transformDCBlock(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation) +{ + size_t i; + + if(bFlipV[oOrientation]) + for(i = 0; i < 16; i += 4) + pOrg[i + 1] = -pOrg[i + 1], pOrg[i + 3] = -pOrg[i + 3]; + + if(bFlipH[oOrientation]) + for(i = 0; i < 4; i ++) + pOrg[i + 4] = -pOrg[i + 4], pOrg[i + 12] = -pOrg[i + 12]; + + if(oOrientation < O_RCW) + memcpy(pDst, pOrg, 16 * sizeof(PixelI)); + else + for(i = 0; i < 16; i ++) + pDst[i] = pOrg[(i >> 2) + ((i & 3) << 2)]; +} + +Void transformDCBlock422(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation) +{ + assert(oOrientation < O_RCW); + + if(bFlipV[oOrientation]) + pOrg[1] = -pOrg[1], pOrg[3] = -pOrg[3], pOrg[4] = -pOrg[4], pOrg[5] = -pOrg[5], pOrg[7] = -pOrg[7]; + + if(bFlipH[oOrientation]) + pOrg[2] = -pOrg[2], pOrg[3] = -pOrg[3], pOrg[6] = -pOrg[6], pOrg[7] = -pOrg[7]; + + if(bFlipV[oOrientation]) + pDst[0] = pOrg[0], pDst[1] = pOrg[5], pDst[2] = pOrg[6], pDst[3] = pOrg[7], pDst[4] = pOrg[4], pDst[5] = pOrg[1], pDst[6] = pOrg[2], pDst[7] = pOrg[3]; + else + memcpy(pDst, pOrg, 8 * sizeof(PixelI)); +} + +Void transformDCBlock420(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation) +{ + if(bFlipV[oOrientation]) + pOrg[1] = -pOrg[1], pOrg[3] = -pOrg[3]; + + if(bFlipH[oOrientation]) + pOrg[2] = -pOrg[2], pOrg[3] = -pOrg[3]; + + pDst[0] = pOrg[0], pDst[3] = pOrg[3]; + if(oOrientation < O_RCW) + pDst[1] = pOrg[1], pDst[2] = pOrg[2]; + else + pDst[1] = pOrg[2], pDst[2] = pOrg[1]; +} + +Void transformACBlocks(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation) +{ + PixelI * pO, * pD; + const Int * pT = dctIndex[0]; + size_t i, j, k; + + for(j = 0, pO = pOrg; j < 16; j ++, pO += 16){ + if(bFlipV[oOrientation]) + for(i = 0; i < 16; i += 4) + pO[pT[i + 1]] = -pO[pT[i + 1]], pO[pT[i + 3]] = -pO[pT[i + 3]]; + + if(bFlipH[oOrientation]) + for(i = 0; i < 4; i ++) + pO[pT[i + 4]] = -pO[pT[i + 4]], pO[pT[i + 12]] = -pO[pT[i + 12]]; + } + + for(j = 0; j < 4; j ++) + for(i = 0; i < 4; i ++){ + size_t ii = (bFlipV[oOrientation] ? 3 - i : i); + size_t jj = (bFlipH[oOrientation] ? 3 - j : j); + + if(oOrientation < O_RCW) + memcpy(pDst + (jj * 4 + ii) * 16, pOrg + (j * 4 + i) * 16, 16 * sizeof(PixelI)); + else{ + pO = pOrg + (j * 4 + i) * 16; + pD = pDst + (ii * 4 + jj) * 16; + for(k = 1; k < 16; k ++) + pD[pT[k]] = pO[pT[(k >> 2) + ((k & 3) << 2)]]; + } + } +} + +Void transformACBlocks422(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation) +{ + PixelI * pO; + const Int * pT = dctIndex[0]; + size_t i, j; + + assert(oOrientation < O_RCW); + + for(j = 0, pO = pOrg; j < 8; j ++, pO += 16){ + if(bFlipV[oOrientation]) + for(i = 0; i < 16; i += 4) + pO[pT[i + 1]] = -pO[pT[i + 1]], pO[pT[i + 3]] = -pO[pT[i + 3]]; + + if(bFlipH[oOrientation]) + for(i = 0; i < 4; i ++) + pO[pT[i + 4]] = -pO[pT[i + 4]], pO[pT[i + 12]] = -pO[pT[i + 12]]; + } + + for(j = 0; j < 2; j ++) + for(i = 0; i < 4; i ++){ + size_t ii = (bFlipV[oOrientation] ? 3 - i : i); + size_t jj = (bFlipH[oOrientation] ? 1 - j : j); + + memcpy(pDst + (jj * 4 + ii) * 16, pOrg + (j * 4 + i) * 16, 16 * sizeof(PixelI)); + } +} + +Void transformACBlocks420(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation) +{ + PixelI * pO, * pD; + const Int * pT = dctIndex[0]; + size_t i, j, k; + + for(j = 0, pO = pOrg; j < 4; j ++, pO += 16){ + if(bFlipV[oOrientation]) + for(i = 0; i < 16; i += 4) + pO[pT[i + 1]] = -pO[pT[i + 1]], pO[pT[i + 3]] = -pO[pT[i + 3]]; + + if(bFlipH[oOrientation]) + for(i = 0; i < 4; i ++) + pO[pT[i + 4]] = -pO[pT[i + 4]], pO[pT[i + 12]] = -pO[pT[i + 12]]; + } + + for(j = 0; j < 2; j ++) + for(i = 0; i < 2; i ++){ + size_t ii = (bFlipV[oOrientation] ? 1 - i : i); + size_t jj = (bFlipH[oOrientation] ? 1 - j : j); + + if(oOrientation < O_RCW) + memcpy(pDst + (jj * 2 + ii) * 16, pOrg + (j * 2 + i) * 16, 16 * sizeof(PixelI)); + else{ + pO = pOrg + (j * 2 + i) * 16; + pD = pDst + (ii * 2 + jj) * 16; + for(k = 1; k < 16; k ++) + pD[pT[k]] = pO[pT[(k >> 2) + ((k & 3) << 2)]]; + } + } +} + +Int getROI(CWMImageInfo * pII, CCoreParameters * pCore, CWMIStrCodecParam * pSCP, CWMTranscodingParam * pParam) +{ + const ORIENTATION oO = pParam->oOrientation; + size_t iLeft, iTop, cWidth, cHeight, i, j; + size_t mbLeft, mbRight, mbTop, mbBottom; + size_t * iTile = (size_t *)malloc(MAX_TILES * sizeof(size_t)); + + if(iTile == NULL) + return ICERR_ERROR; + + if(pParam->cLeftX + pParam->cWidth > pII->cWidth || pParam->cTopY + pParam->cHeight > pII->cHeight) // invalid region + return ICERR_ERROR; + + cWidth = pParam->cWidth, cHeight = pParam->cHeight; + iLeft = pParam->cLeftX + pCore->cExtraPixelsLeft, iTop = pParam->cTopY + pCore->cExtraPixelsTop; + if(pSCP->olOverlap != OL_NONE && pParam->bIgnoreOverlap == FALSE){ // include pixels borrowed + size_t cBlurred = (pSCP->olOverlap == OL_TWO ? 10 : 2); + + if(iLeft > cBlurred) + iLeft -= cBlurred, cWidth += cBlurred; + else + cWidth += iLeft, iLeft = 0; + if(iTop > cBlurred) + iTop -= cBlurred, cHeight += cBlurred; + else + cHeight += iTop, iTop = 0; + cWidth += cBlurred, cHeight += cBlurred; + if(iLeft + cWidth > pII->cWidth + pCore->cExtraPixelsLeft + pCore->cExtraPixelsRight) + cWidth = pII->cWidth + pCore->cExtraPixelsLeft + pCore->cExtraPixelsRight - iLeft; + if(iTop + cHeight > pII->cHeight + pCore->cExtraPixelsTop + pCore->cExtraPixelsBottom) + cHeight = pII->cHeight + pCore->cExtraPixelsTop + pCore->cExtraPixelsBottom - iTop; + } + + mbTop = (iTop >> 4), mbLeft = (iLeft >> 4); + mbBottom = (iTop + cHeight + 15) >> 4, mbRight = (iLeft + cWidth + 15) >> 4; + pCore->cExtraPixelsLeft += pParam->cLeftX - (mbLeft << 4); + pCore->cExtraPixelsRight = ((mbRight - mbLeft) << 4) - pParam->cWidth - pCore->cExtraPixelsLeft; + pCore->cExtraPixelsTop += pParam->cTopY - (mbTop << 4); + pCore->cExtraPixelsBottom = ((mbBottom - mbTop) << 4) - pParam->cHeight - pCore->cExtraPixelsTop; + + pII->cWidth = ((mbRight - mbLeft) << 4) - pCore->cExtraPixelsLeft - pCore->cExtraPixelsRight; + pII->cHeight = ((mbBottom - mbTop) << 4) - pCore->cExtraPixelsTop - pCore->cExtraPixelsBottom; + pParam->cLeftX = iLeft, pParam->cTopY = iTop; + pParam->cWidth = cWidth, pParam->cHeight = cHeight; + + // extra pixels in transformed space +#define SWAP(a, b) i = a, a = b, b = i + if(oO == O_FLIPH || oO == O_FLIPVH || oO == O_RCW_FLIPV || oO == O_RCW_FLIPVH) + SWAP(pCore->cExtraPixelsLeft, pCore->cExtraPixelsRight); + if(oO == O_FLIPV || oO == O_FLIPVH || oO == O_RCW || oO == O_RCW_FLIPV) + SWAP(pCore->cExtraPixelsTop, pCore->cExtraPixelsBottom); + if(oO >= O_RCW){ + SWAP(pCore->cExtraPixelsLeft, pCore->cExtraPixelsTop); + SWAP(pCore->cExtraPixelsRight, pCore->cExtraPixelsBottom); + } + + // adjust tiling + for(i = 0, j = 0, iTile[0] = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++) + if((size_t)pSCP->uiTileX[i] >= mbLeft && (size_t)pSCP->uiTileX[i] < mbRight){ + if(j >= MAX_TILES) + j = MAX_TILES - 1; + iTile[j] = (size_t)pSCP->uiTileX[i] - mbLeft, j ++; + } + if(iTile[0] == 0) + for(i = 0, pSCP->cNumOfSliceMinus1V = (j == 0 ? 0 : (U32)(j - 1)); i < j; i ++) + pSCP->uiTileX[i] = (U32)iTile[i]; + else + for(i = 1, pSCP->uiTileX[0] = 0, pSCP->cNumOfSliceMinus1V = (U32)j; i <= j; i ++) + pSCP->uiTileX[i] = (U32)iTile[i - 1]; + if(oO == O_FLIPH || oO == O_FLIPVH || oO == O_RCW_FLIPV || oO == O_RCW_FLIPVH){ // reverse order + for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++) + iTile[i] = mbRight - mbLeft - (size_t)pSCP->uiTileX[i]; + for(i = 1, pSCP->uiTileX[0] = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++) + pSCP->uiTileX[i] = (U32)(iTile[(size_t)pSCP->cNumOfSliceMinus1V - i + 1]); + } + for(i = 0, j = 0, iTile[0] = 0; i <= (size_t)pSCP->cNumOfSliceMinus1H; i ++) + if(pSCP->uiTileY[i] >= mbTop && pSCP->uiTileY[i] < mbBottom){ + if(j >= MAX_TILES) + j = MAX_TILES - 1; + iTile[j] = (size_t)pSCP->uiTileY[i] - mbTop, j ++; + } + if(iTile[0] == 0) + for(i = 0, pSCP->cNumOfSliceMinus1H = (j == 0 ? 0 : (U32)(j - 1)); i < j; i ++) + pSCP->uiTileY[i] = (U32)iTile[i]; + else + for(i = 1, pSCP->uiTileY[0] = 0, pSCP->cNumOfSliceMinus1H = (U32)j; i <= j; i ++) + pSCP->uiTileY[i] = (U32)iTile[i - 1]; + if(oO == O_FLIPV || oO == O_FLIPVH || oO == O_RCW || oO == O_RCW_FLIPV){ // reverse order + for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1H; i ++) + iTile[i] = mbBottom - mbTop - (size_t)pSCP->uiTileY[i]; + for(i = 1, pSCP->uiTileY[0] = 0; i <= (size_t)pSCP->cNumOfSliceMinus1H; i ++) + pSCP->uiTileY[i] = (U32)(iTile[(size_t)pSCP->cNumOfSliceMinus1H - i + 1]); + } + if(oO >= O_RCW){ // switch X & Y + for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++) + iTile[i] = (size_t)pSCP->uiTileX[i]; + for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1H; i ++) + pSCP->uiTileX[i] = pSCP->uiTileY[i]; + for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++) + pSCP->uiTileY[i] = (U32)iTile[i]; + i = (size_t)pSCP->cNumOfSliceMinus1H, pSCP->cNumOfSliceMinus1H = pSCP->cNumOfSliceMinus1V, pSCP->cNumOfSliceMinus1V = (U32)i; + } + + free(iTile); + + return ICERR_OK; +} + +Bool isTileBoundary(U32 * pTilePos, U32 cTiles, U32 cMBs, U32 iPos) +{ + U32 i; + + for(i = 0; i < cTiles; i ++) + if(iPos == pTilePos[i] * 16) + break; + + return ((i < cTiles || (iPos + 15) / 16 >= cMBs) ? TRUE : FALSE); +} + +Bool isTileExtraction(CWMImageStrCodec * pSC, CWMTranscodingParam * pParam) +{ + if(pParam->bIgnoreOverlap == FALSE && pSC->WMISCP.olOverlap == OL_NONE) + pParam->bIgnoreOverlap = TRUE; + + if(pParam->bIgnoreOverlap == TRUE && pParam->oOrientation == O_NONE && pParam->bfBitstreamFormat == pSC->WMISCP.bfBitstreamFormat){ + if(pParam->bfBitstreamFormat == SPATIAL && pParam->sbSubband != pSC->WMISCP.sbSubband) + return FALSE; + + return (isTileBoundary(pSC->WMISCP.uiTileX, pSC->WMISCP.cNumOfSliceMinus1V + 1, (U32)pSC->cmbWidth, (U32)(pParam->cLeftX + pSC->m_param.cExtraPixelsLeft)) && + isTileBoundary(pSC->WMISCP.uiTileY, pSC->WMISCP.cNumOfSliceMinus1H + 1, (U32)pSC->cmbHeight, (U32)(pParam->cTopY + pSC->m_param.cExtraPixelsTop)) && + isTileBoundary(pSC->WMISCP.uiTileX, pSC->WMISCP.cNumOfSliceMinus1V + 1, (U32)pSC->cmbWidth, (U32)(pParam->cLeftX + pParam->cWidth + pSC->m_param.cExtraPixelsLeft)) && + isTileBoundary(pSC->WMISCP.uiTileY, pSC->WMISCP.cNumOfSliceMinus1H + 1, (U32)pSC->cmbHeight, (U32)(pParam->cTopY + pParam->cHeight + pSC->m_param.cExtraPixelsTop))); + } + + return FALSE; +} + +Int WMPhotoTranscode(struct WMPStream * pStreamIn, struct WMPStream * pStreamOut, CWMTranscodingParam * pParam) +{ + PixelI * pMBBuf, MBBufAlpha[256]; // shared buffer, decoder <=> encoder bridge + PixelI * pFrameBuf = NULL, * pFrameBufAlpha = NULL; + CWMIMBInfo * pMBInfo = NULL, * pMBInfoAlpha = NULL; + CWMImageStrCodec * pSCDec, * pSCEnc, * pSC; + CWMDecoderParameters aDecoderParam = {0}; + U8 * pIOHeaderDec, * pIOHeaderEnc; + CCodingContext * pContext; + CTileQPInfo * pTileQPInfo = NULL; + ORIENTATION oO = pParam->oOrientation; + size_t iAlphaPos = 0; + size_t cUnit; + size_t i, j, mbLeft, mbRight, mbTop, mbBottom, mbWidth, mbHeight; + + if(pStreamIn == NULL || pStreamOut == NULL || pParam == NULL) + return ICERR_ERROR; + + // initialize decoder + if((pSCDec = (CWMImageStrCodec *)malloc(sizeof(CWMImageStrCodec))) == NULL) + return ICERR_ERROR; + memset(pSCDec, 0, sizeof(CWMImageStrCodec)); + + pSCDec->WMISCP.pWStream = pStreamIn; + if(ReadWMIHeader(&pSCDec->WMII, &pSCDec->WMISCP, &pSCDec->m_param) != ICERR_OK) + return ICERR_ERROR; + + if(pSCDec->WMISCP.cfColorFormat == YUV_422 && oO >= O_RCW) + pParam->oOrientation = oO = O_NONE; // Can not rotate 422 in compressed domain! + + pSCDec->cmbWidth = (pSCDec->WMII.cWidth + pSCDec->m_param.cExtraPixelsLeft + pSCDec->m_param.cExtraPixelsRight + 15) / 16; + pSCDec->cmbHeight = (pSCDec->WMII.cHeight + pSCDec->m_param.cExtraPixelsTop + pSCDec->m_param.cExtraPixelsBottom + 15) / 16; + pSCDec->m_param.cNumChannels = pSCDec->WMISCP.cChannel; + pSCDec->m_Dparam = &aDecoderParam; + pSCDec->m_Dparam->bSkipFlexbits = (pSCDec->WMISCP.sbSubband == SB_NO_FLEXBITS); + pSCDec->m_param.bTranscode = TRUE; + + pParam->bIgnoreOverlap = isTileExtraction(pSCDec, pParam); + + cUnit = (pSCDec->m_param.cfColorFormat == YUV_420 ? 384 : (pSCDec->m_param.cfColorFormat == YUV_422 ? 512 : 256 * pSCDec->m_param.cNumChannels)); + if(cUnit > 256 * MAX_CHANNELS) + return ICERR_ERROR; + pSCDec->p1MBbuffer[0] = pMBBuf = (PixelI *)malloc(cUnit * sizeof(PixelI)); + if(pMBBuf == NULL) + return ICERR_ERROR; + pSCDec->p1MBbuffer[1] = pSCDec->p1MBbuffer[0] + 256; + for(i = 2; i < pSCDec->m_param.cNumChannels; i ++) + pSCDec->p1MBbuffer[i] = pSCDec->p1MBbuffer[i - 1] + (pSCDec->m_param.cfColorFormat == YUV_420 ? 64 : (pSCDec->m_param.cfColorFormat == YUV_422 ? 128 : 256)); + + if(pSCDec->m_param.bAlphaChannel){ // alpha channel + SimpleBitIO SB = {0}; + + iAlphaPos = pSCDec->m_param.cNumChannels; + if((pSCDec->m_pNextSC = (CWMImageStrCodec *)malloc(sizeof(CWMImageStrCodec))) == NULL) + return ICERR_ERROR; + *pSCDec->m_pNextSC = *pSCDec; + pSCDec->m_pNextSC->p1MBbuffer[0] = MBBufAlpha; + pSCDec->m_pNextSC->WMISCP.cfColorFormat = pSCDec->m_pNextSC->WMII.cfColorFormat = pSCDec->m_pNextSC->m_param.cfColorFormat = Y_ONLY; + pSCDec->m_pNextSC->WMISCP.cChannel = pSCDec->m_pNextSC->m_param.cNumChannels = 1; + pSCDec->m_pNextSC->m_bSecondary = TRUE; + pSCDec->m_pNextSC->m_pNextSC = pSCDec; + + // read plane header of second image plane + if(attach_SB(&SB, pSCDec->WMISCP.pWStream) != ICERR_OK) + return ICERR_ERROR; + ReadImagePlaneHeader(&pSCDec->m_pNextSC->WMII, &pSCDec->m_pNextSC->WMISCP, &pSCDec->m_pNextSC->m_param, &SB); + detach_SB(&SB); + + if(StrDecInit(pSCDec->m_pNextSC) != ICERR_OK) + return ICERR_ERROR; + } + else + pParam->uAlphaMode = 0; + + pIOHeaderDec = (U8 *)malloc((PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 + sizeof(BitIOInfo)); + if(pIOHeaderDec == NULL) + return ICERR_ERROR; + memset(pIOHeaderDec, 0, (PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 + sizeof(BitIOInfo)); + pSCDec->pIOHeader = (BitIOInfo *)((U8 *)ALIGNUP(pIOHeaderDec, PACKETLENGTH * 4) + PACKETLENGTH * 2); + + if(StrIODecInit(pSCDec) != ICERR_OK) + return ICERR_ERROR; + + if(StrDecInit(pSCDec) != ICERR_OK) + return ICERR_ERROR; + + if(pSCDec->m_param.bAlphaChannel){ // alpha channel + if(StrDecInit(pSCDec->m_pNextSC) != ICERR_OK) + return ICERR_ERROR; + } + + // initialize encoder + if((pSCEnc = (CWMImageStrCodec *)malloc(sizeof(CWMImageStrCodec))) == NULL) + return ICERR_ERROR; + memset(pSCEnc, 0, sizeof(CWMImageStrCodec)); + + pSCEnc->WMII = pSCDec->WMII; + pSCEnc->WMISCP = pSCDec->WMISCP; + pSCEnc->m_param = pSCDec->m_param; + pSCEnc->WMISCP.pWStream = pStreamOut; + pSCEnc->WMISCP.bfBitstreamFormat = pParam->bfBitstreamFormat; +// pSCEnc->m_param.cfColorFormat = pSCEnc->WMISCP.cfColorFormat = pParam->cfColorFormat; + pSCEnc->m_param.cfColorFormat = pSCEnc->WMISCP.cfColorFormat; + pSCEnc->m_param.cNumChannels = (pSCEnc->WMISCP.cfColorFormat == Y_ONLY ? 1 : (pSCEnc->WMISCP.cfColorFormat == YUV_444 ? 3 : pSCEnc->WMISCP.cChannel)); + pSCEnc->m_param.bAlphaChannel = (pParam->uAlphaMode > 0); + pSCEnc->m_param.bTranscode = TRUE; + if(pParam->sbSubband >= SB_MAX) + pParam->sbSubband = SB_ALL; + if(pParam->sbSubband > pSCEnc->WMISCP.sbSubband) + pSCEnc->WMISCP.sbSubband = pParam->sbSubband; + pSCEnc->m_bSecondary = FALSE; + + pIOHeaderEnc = (U8 *)malloc((PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 + sizeof(BitIOInfo)); + if(pIOHeaderEnc == NULL) + return ICERR_ERROR; + memset(pIOHeaderEnc, 0, (PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 + sizeof(BitIOInfo)); + pSCEnc->pIOHeader = (BitIOInfo *)((U8 *)ALIGNUP(pIOHeaderEnc, PACKETLENGTH * 4) + PACKETLENGTH * 2); + + for(i = 0; i < pSCEnc->m_param.cNumChannels; i ++) + pSCEnc->pPlane[i] = pSCDec->p1MBbuffer[i]; + + for(i = 1; i < pSCDec->cNumBitIO * (pSCDec->WMISCP.cNumOfSliceMinus1H + 1); i ++){ + if(pSCDec->pIndexTable[i] == 0 && i + 1 != pSCDec->cNumBitIO * (pSCDec->WMISCP.cNumOfSliceMinus1H + 1)) // empty packet + pSCDec->pIndexTable[i] = pSCDec->pIndexTable[i + 1]; + if(pSCDec->pIndexTable[i] != 0 && pSCDec->pIndexTable[i] < pSCDec->pIndexTable[i - 1]) // out of order bitstream, can not do fast tile extraction! + pParam->bIgnoreOverlap = FALSE; + } + + if(getROI(&pSCEnc->WMII, &pSCEnc->m_param, &pSCEnc->WMISCP, pParam) != ICERR_OK) + return ICERR_ERROR; + + mbLeft = (pParam->cLeftX >> 4); + mbRight = ((pParam->cLeftX + pParam->cWidth + 15) >> 4); + mbTop = (pParam->cTopY >> 4); + mbBottom = ((pParam->cTopY + pParam->cHeight + 15) >> 4); + + if(pSCDec->WMISCP.uiTileX[pSCDec->WMISCP.cNumOfSliceMinus1V] >= mbLeft && pSCDec->WMISCP.uiTileX[pSCDec->WMISCP.cNumOfSliceMinus1V] <= mbRight && + pSCDec->WMISCP.uiTileY[pSCDec->WMISCP.cNumOfSliceMinus1H] >= mbTop && pSCDec->WMISCP.uiTileY[pSCDec->WMISCP.cNumOfSliceMinus1H] <= mbBottom) + pParam->bIgnoreOverlap = FALSE; + + pSCEnc->bTileExtraction = pParam->bIgnoreOverlap; + + mbWidth = pSCEnc->cmbWidth = mbRight - mbLeft; + mbHeight = pSCEnc->cmbHeight = mbBottom - mbTop; + if(oO >= O_RCW){ + SWAP(pSCEnc->WMII.cWidth, pSCEnc->WMII.cHeight); + SWAP(pSCEnc->cmbWidth, pSCEnc->cmbHeight); + } + + if(oO != O_NONE){ + pFrameBuf = (PixelI *)malloc(pSCEnc->cmbWidth * pSCEnc->cmbHeight * cUnit * sizeof(PixelI)); + if(pFrameBuf == NULL || (pSCEnc->cmbWidth * pSCEnc->cmbHeight * cUnit * sizeof(PixelI) < pSCEnc->cmbWidth * pSCEnc->cmbHeight * cUnit)) + return ICERR_ERROR; + pMBInfo = (CWMIMBInfo *)malloc(pSCEnc->cmbWidth * pSCEnc->cmbHeight * sizeof(CWMIMBInfo)); + if(pMBInfo == NULL || (pSCEnc->cmbWidth * pSCEnc->cmbHeight * sizeof(CWMIMBInfo) < pSCEnc->cmbWidth * pSCEnc->cmbHeight)) + return ICERR_ERROR; + if(pParam->uAlphaMode > 0){ // alpha channel + pFrameBufAlpha = (PixelI *)malloc(pSCEnc->cmbWidth * pSCEnc->cmbHeight * 256 * sizeof(PixelI)); + if(pFrameBufAlpha == NULL || (pSCEnc->cmbWidth * pSCEnc->cmbHeight * 256 * sizeof(PixelI) < pSCEnc->cmbWidth * pSCEnc->cmbHeight * 256)) + return ICERR_ERROR; + pMBInfoAlpha = (CWMIMBInfo *)malloc(pSCEnc->cmbWidth * pSCEnc->cmbHeight * sizeof(CWMIMBInfo)); + if(pMBInfoAlpha == NULL || (pSCEnc->cmbWidth * pSCEnc->cmbHeight * sizeof(CWMIMBInfo) < pSCEnc->cmbWidth * pSCEnc->cmbHeight)) + return ICERR_ERROR; + } + } + + if(oO < O_RCW && pSCEnc->WMII.oOrientation < O_RCW) + pSCEnc->WMII.oOrientation ^= oO; + else if(oO >= O_RCW && pSCEnc->WMII.oOrientation >= O_RCW){ + pSCEnc->WMII.oOrientation ^= oO; + pSCEnc->WMII.oOrientation = (pSCEnc->WMII.oOrientation & 1) * 2 + (pSCEnc->WMII.oOrientation >> 1); + } + else if(oO >= O_RCW && pSCEnc->WMII.oOrientation < O_RCW) + pSCEnc->WMII.oOrientation = oO ^ ((pSCEnc->WMII.oOrientation & 1) * 2 + (pSCEnc->WMII.oOrientation >> 1)); + else + pSCEnc->WMII.oOrientation ^= ((oO & 1) * 2 + (oO >> 1)); + +// pSCEnc->WMISCP.nExpBias += 128; + + if(pParam->bIgnoreOverlap == TRUE){ + attachISWrite(pSCEnc->pIOHeader, pSCEnc->WMISCP.pWStream); + pSCEnc->pTile = pSCDec->pTile; + if(pSCEnc->WMISCP.cNumOfSliceMinus1H + pSCEnc->WMISCP.cNumOfSliceMinus1V == 0 && pSCEnc->WMISCP.bfBitstreamFormat == SPATIAL) + pSCEnc->m_param.bIndexTable = FALSE; + WriteWMIHeader(pSCEnc); + } + else{ + pTileQPInfo = (CTileQPInfo *)malloc((oO == O_NONE ? 1 : (pSCEnc->WMISCP.cNumOfSliceMinus1H + 1) * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1)) * sizeof( CTileQPInfo)); + if(pTileQPInfo == NULL || ((oO == O_NONE ? 1 : (pSCEnc->WMISCP.cNumOfSliceMinus1H + 1) * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1)) * sizeof( CTileQPInfo) < (oO == O_NONE ? 1 : (pSCEnc->WMISCP.cNumOfSliceMinus1H + 1) * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1)))) + return ICERR_ERROR; + + if(StrEncInit(pSCEnc) != ICERR_OK) + return ICERR_ERROR; + } + + if(pParam->uAlphaMode > 0){ // alpha channel +// pSCEnc->WMISCP.nExpBias -= 128; + if((pSCEnc->m_pNextSC = (CWMImageStrCodec *)malloc(sizeof(CWMImageStrCodec))) == NULL) + return ICERR_ERROR; + *pSCEnc->m_pNextSC = *pSCEnc; + pSCEnc->m_pNextSC->pPlane[0] = pSCDec->m_pNextSC->p1MBbuffer[0]; + pSCEnc->m_pNextSC->WMISCP.cfColorFormat = pSCEnc->m_pNextSC->WMII.cfColorFormat = pSCEnc->m_pNextSC->m_param.cfColorFormat = Y_ONLY; + pSCEnc->m_pNextSC->WMISCP.cChannel = pSCEnc->m_pNextSC->m_param.cNumChannels = 1; + pSCEnc->m_pNextSC->m_bSecondary = TRUE; + pSCEnc->m_pNextSC->m_pNextSC = pSCEnc; + pSCEnc->m_pNextSC->m_param = pSCDec->m_pNextSC->m_param; + pSCEnc->m_param.bAlphaChannel = TRUE; + + if(pParam->bIgnoreOverlap == TRUE) + pSCEnc->m_pNextSC->pTile = pSCDec->m_pNextSC->pTile; + else if(StrEncInit(pSCEnc->m_pNextSC) != ICERR_OK) + return ICERR_ERROR; + + WriteImagePlaneHeader(pSCEnc->m_pNextSC); + } + + if(pParam->bIgnoreOverlap == TRUE){ + SUBBAND sbEnc = pSCEnc->WMISCP.sbSubband, sbDec = pSCDec->WMISCP.sbSubband; + size_t cfEnc = ((pSCEnc->WMISCP.bfBitstreamFormat == SPATIAL || sbEnc == SB_DC_ONLY) ? 1 : (sbEnc == SB_NO_HIGHPASS ? 2 : (sbEnc == SB_NO_FLEXBITS ? 3 : 4))); + size_t cfDec = ((pSCDec->WMISCP.bfBitstreamFormat == SPATIAL || sbDec == SB_DC_ONLY) ? 1 : (sbDec == SB_NO_HIGHPASS ? 2 : (sbDec == SB_NO_FLEXBITS ? 3 : 4))); + size_t k, l = 0; + + pSCEnc->pIndexTable = (size_t *)malloc(sizeof(size_t) * (pSCEnc->WMISCP.cNumOfSliceMinus1H + 1) * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1) * cfEnc); + + if(pSCEnc->pIndexTable == NULL || cfEnc > cfDec) + return ICERR_ERROR; + + pSCEnc->cNumBitIO = cfEnc * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1); + + for(j = 0; j <= pSCDec->WMISCP.cNumOfSliceMinus1H; j ++){ + for(i = 0; i <= pSCDec->WMISCP.cNumOfSliceMinus1V; i ++) + if(pSCDec->WMISCP.uiTileX[i] >= mbLeft && pSCDec->WMISCP.uiTileX[i] < mbRight && + pSCDec->WMISCP.uiTileY[j] >= mbTop && pSCDec->WMISCP.uiTileY[j] < mbBottom){ + for(k = 0; k < cfEnc; k ++, l ++) + pSCEnc->pIndexTable[l] = pSCDec->pIndexTable[(j * (pSCDec->WMISCP.cNumOfSliceMinus1V + 1) + i) * cfDec + k + 1] - pSCDec->pIndexTable[(j * (pSCDec->WMISCP.cNumOfSliceMinus1V + 1) + i) * cfDec + k]; + } + } + + if(pSCEnc->WMISCP.cNumOfSliceMinus1H + pSCEnc->WMISCP.cNumOfSliceMinus1V == 0 && pSCEnc->WMISCP.bfBitstreamFormat == SPATIAL){ + pSCEnc->m_param.bIndexTable = FALSE; + pSCEnc->cNumBitIO = 0; + writeIndexTableNull(pSCEnc); + } + else + writeIndexTable(pSCEnc); + + detachISWrite(pSCEnc, pSCEnc->pIOHeader); + + for(j = l = 0; j <= pSCDec->WMISCP.cNumOfSliceMinus1H; j ++){ + for(i = 0; i <= pSCDec->WMISCP.cNumOfSliceMinus1V; i ++) + if(pSCDec->WMISCP.uiTileX[i] >= mbLeft && pSCDec->WMISCP.uiTileX[i] < mbRight && + pSCDec->WMISCP.uiTileY[j] >= mbTop && pSCDec->WMISCP.uiTileY[j] < mbBottom){ + for(k = 0; k < cfEnc; k ++){ + pSCDec->WMISCP.pWStream->SetPos(pSCDec->WMISCP.pWStream, pSCDec->pIndexTable[(j * (pSCDec->WMISCP.cNumOfSliceMinus1V + 1) + i) * cfDec + k] + pSCDec->cHeaderSize); + copyTo(pSCDec->WMISCP.pWStream, pSCEnc->WMISCP.pWStream, pSCEnc->pIndexTable[l++]); + } + } + } + + free(pSCEnc->pIndexTable); + } + else + writeIndexTableNull(pSCEnc); + + for(pSCDec->cRow = 0; pSCDec->cRow < mbBottom && pParam->bIgnoreOverlap == FALSE; pSCDec->cRow ++){ + for(pSCDec->cColumn = 0; pSCDec->cColumn < pSCDec->cmbWidth; pSCDec->cColumn ++){ + Int cRow = (Int)pSCDec->cRow, cColumn = (Int)pSCDec->cColumn; + CWMITile * pTile; + + memset(pMBBuf, 0, sizeof(PixelI) * cUnit); + if(pSCDec->m_param.bAlphaChannel){ // alpha channel + memset(pSCDec->m_pNextSC->p1MBbuffer[0], 0, sizeof(PixelI) * 256); + pSCDec->m_pNextSC->cRow = pSCDec->cRow; + pSCDec->m_pNextSC->cColumn = pSCDec->cColumn; + } + + // decode + pSC = pSCDec; + for(i = (pSCDec->m_param.bAlphaChannel ? 2 : 1); i > 0; i --){ + getTilePos(pSCDec, cColumn, cRow); + if(i == 2){ + pSCDec->m_pNextSC->cTileColumn = pSCDec->cTileColumn; + pSCDec->m_pNextSC->cTileRow = pSCDec->cTileRow; + } + + if(readPackets(pSCDec) != ICERR_OK) + return ICERR_ERROR; + + pContext = &pSCDec->m_pCodingContext[pSCDec->cTileColumn]; + + if(DecodeMacroblockDC(pSCDec, pContext, cColumn, cRow) != ICERR_OK) + return ICERR_ERROR; + + if(pSCDec->cSB > 1) + if(DecodeMacroblockLowpass(pSCDec, pContext, cColumn, cRow) != ICERR_OK) + return ICERR_ERROR; + + predDCACDec(pSCDec); + + if(pSCDec->cSB > 2) + if(DecodeMacroblockHighpass(pSCDec, pContext, cColumn, cRow) != ICERR_OK) + return ICERR_ERROR; + + predACDec(pSCDec); + + updatePredInfo(pSCDec, &pSCDec->MBInfo, cColumn, pSCDec->WMISCP.cfColorFormat); + + pSCDec = pSCDec->m_pNextSC; + } + pSCDec = pSC; + + if(pSCDec->cRow >= mbTop && pSCDec->cColumn >= mbLeft && pSCDec->cColumn < mbRight){ + cRow = (Int)(pSCDec->cRow - mbTop); + if(bFlipV[oO]) + cRow = (Int)mbHeight - cRow - 1; + cColumn = (Int)(pSCDec->cColumn - mbLeft); + if(bFlipH[oO]) + cColumn = (Int)mbWidth - cColumn - 1; + + pSCEnc->m_bCtxLeft = pSCEnc->m_bCtxTop = FALSE; + for(i = 0; i <= pSCEnc->WMISCP.cNumOfSliceMinus1H; i ++) + if(pSCEnc->WMISCP.uiTileY[i] == (U32)(oO < O_RCW ? cRow : cColumn)){ + pSCEnc->cTileRow = i; + pSCEnc->m_bCtxTop = TRUE; + break; + } + for(i = 0; i <= pSCEnc->WMISCP.cNumOfSliceMinus1V; i ++) + if(pSCEnc->WMISCP.uiTileX[i] == (U32)(oO < O_RCW ? cColumn : cRow)){ + pSCEnc->cTileColumn = i; + pSCEnc->m_bCtxLeft = TRUE; + break; + } + + if(pSCEnc->m_bCtxLeft && pSCEnc->m_bCtxTop){ // a new tile, buffer tile DQuant info + CTileQPInfo * pTmp = pTileQPInfo; + + pTile = pSCDec->pTile + pSCDec->cTileColumn; + + if(oO != O_NONE) + pTmp += pSCEnc->cTileRow * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1) + pSCEnc->cTileColumn; + + pTmp->dcMode = pTile->cChModeDC; + for(i = 0; i < pSCEnc->WMISCP.cChannel; i ++) + pTmp->dcIndex[i] = pTile->pQuantizerDC[i][0].iIndex; + + if(pSCEnc->WMISCP.sbSubband != SB_DC_ONLY){ + pTmp->bUseDC = pTile->bUseDC; + pTmp->lpNum = pTile->cNumQPLP; + if(pTmp->bUseDC == FALSE) + for(j = 0; j < pTmp->lpNum; j ++){ + pTmp->lpMode[j] = pTile->cChModeLP[j]; + for(i = 0; i < pSCEnc->WMISCP.cChannel; i ++) + pTmp->lpIndex[j][i] = pTile->pQuantizerLP[i][j].iIndex; + } + + if(pSCEnc->WMISCP.sbSubband != SB_NO_HIGHPASS){ + pTmp->bUseLP = pTile->bUseLP; + pTmp->hpNum = pTile->cNumQPHP; + if(pTmp->bUseLP == FALSE) + for(j = 0; j < pTmp->hpNum; j ++){ + pTmp->hpMode[j] = pTile->cChModeHP[j]; + for(i = 0; i < pSCEnc->WMISCP.cChannel; i ++) + pTmp->hpIndex[j][i] = pTile->pQuantizerHP[i][j].iIndex; + } + } + } + + if(pParam->uAlphaMode > 0){ + pTile = pSCDec->m_pNextSC->pTile + pSCDec->cTileColumn; + + pTmp->dcIndex[iAlphaPos] = pTile->pQuantizerDC[0][0].iIndex; + + if(pSCEnc->WMISCP.sbSubband != SB_DC_ONLY){ + pTmp->bUseDCAlpha = pTile->bUseDC; + pTmp->lpNumAlpha = pTile->cNumQPLP; + if(pTmp->bUseDCAlpha == FALSE) + for(j = 0; j < pTmp->lpNumAlpha; j ++) + pTmp->lpIndex[j][iAlphaPos] = pTile->pQuantizerLP[0][j].iIndex; + if(pSCEnc->WMISCP.sbSubband != SB_NO_HIGHPASS){ + pTmp->bUseLPAlpha = pTile->bUseLP; + pTmp->hpNumAlpha = pTile->cNumQPHP; + if(pTmp->bUseLPAlpha == FALSE) + for(j = 0; j < pTmp->hpNumAlpha; j ++) + pTmp->hpIndex[j][iAlphaPos] = pTile->pQuantizerHP[0][j].iIndex; + } + } + } + } + + if(oO == O_NONE){ + // encode + pSCEnc->cColumn = pSCDec->cColumn - mbLeft + 1; + pSCEnc->cRow = pSCDec->cRow + 1 - mbTop; + pSCEnc->MBInfo = pSCDec->MBInfo; + + getTilePos(pSCEnc, cColumn, cRow); + + if(pSCEnc->m_bCtxLeft && pSCEnc->m_bCtxTop) + transcodeTileHeader(pSCEnc, pTileQPInfo); + + if(encodeMB(pSCEnc, cColumn, cRow) != ICERR_OK) + return ICERR_ERROR; + if(pParam->uAlphaMode > 0){ + pSCEnc->m_pNextSC->cColumn = pSCDec->cColumn - mbLeft + 1; + pSCEnc->m_pNextSC->cRow = pSCDec->cRow + 1 - mbTop; + getTilePos(pSCEnc->m_pNextSC, cColumn, cRow); + pSCEnc->m_pNextSC->MBInfo = pSCDec->m_pNextSC->MBInfo; + if(encodeMB(pSCEnc->m_pNextSC, cColumn, cRow) != ICERR_OK) + return ICERR_ERROR; + } + } + else{ + size_t cOff = (oO < O_RCW ? (size_t)cRow * mbWidth + (size_t)cColumn : (size_t)cRow + mbHeight * (size_t)cColumn); + + pMBInfo[cOff] = pSCDec->MBInfo; + + memcpy(&pFrameBuf[cOff * cUnit], pMBBuf, cUnit * sizeof(PixelI)); + + if(pParam->uAlphaMode > 0){ + pMBInfoAlpha[cOff] = pSCDec->m_pNextSC->MBInfo; + + memcpy(&pFrameBufAlpha[cOff * 256], MBBufAlpha, 256 * sizeof(PixelI)); + } + } + } + } + + advanceOneMBRow(pSCDec); + + if(oO == O_NONE) + advanceOneMBRow(pSCEnc); + } + + if(oO != O_NONE){ + for(pSCEnc->cRow = 1; pSCEnc->cRow <= pSCEnc->cmbHeight; pSCEnc->cRow ++){ + for(pSCEnc->cColumn = 1; pSCEnc->cColumn <= pSCEnc->cmbWidth; pSCEnc->cColumn ++){ + Int cRow, cColumn; + size_t cOff = (pSCEnc->cRow - 1) * pSCEnc->cmbWidth + pSCEnc->cColumn - 1; + + for(i = 0; i < ((pSCEnc->m_param.cfColorFormat == YUV_420 || pSCEnc->m_param.cfColorFormat == YUV_422) ? 1 : pSCEnc->m_param.cNumChannels); i ++){ + transformDCBlock(pMBInfo[cOff].iBlockDC[i], pSCEnc->MBInfo.iBlockDC[i], oO); + transformACBlocks(pFrameBuf + cOff * cUnit + i * 256, pMBBuf + 256 * i, oO); + } + if(pSCEnc->WMISCP.cfColorFormat == YUV_420) + for(i = 0; i < 2; i ++){ + transformDCBlock420(pMBInfo[cOff].iBlockDC[i + 1], pSCEnc->MBInfo.iBlockDC[i + 1], oO); + transformACBlocks420(pFrameBuf + cOff * cUnit + 256 + i * 64, pMBBuf + 256 + i * 64, oO); + } + else if(pSCEnc->WMISCP.cfColorFormat == YUV_422) + for(i = 0; i < 2; i ++){ + transformDCBlock422(pMBInfo[cOff].iBlockDC[i + 1], pSCEnc->MBInfo.iBlockDC[i + 1], oO); + transformACBlocks422(pFrameBuf + cOff * cUnit + 256 + i * 128, pMBBuf + 256 + i * 128, oO); + } + + pSCEnc->MBInfo.iQIndexLP = pMBInfo[cOff].iQIndexLP; + pSCEnc->MBInfo.iQIndexHP = pMBInfo[cOff].iQIndexHP; + + cRow = (Int)pSCEnc->cRow - 1; + cColumn = (Int)pSCEnc->cColumn - 1; + getTilePos(pSCEnc, cColumn, cRow); + + if(pSCEnc->m_bCtxLeft && pSCEnc->m_bCtxTop) + transcodeTileHeader(pSCEnc, pTileQPInfo + pSCEnc->cTileRow * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1) + pSCEnc->cTileColumn); + if(encodeMB(pSCEnc, cColumn, cRow) != ICERR_OK) + return ICERR_ERROR; + + if(pParam->uAlphaMode > 0){ + pSCEnc->m_pNextSC->cColumn = pSCEnc->cColumn; + pSCEnc->m_pNextSC->cRow = pSCEnc->cRow; + getTilePos(pSCEnc->m_pNextSC, cColumn, cRow); + pSCEnc->m_pNextSC->MBInfo = pSCDec->m_pNextSC->MBInfo; + + transformDCBlock(pMBInfoAlpha[cOff].iBlockDC[0], pSCEnc->m_pNextSC->MBInfo.iBlockDC[0], oO); + transformACBlocks(pFrameBufAlpha + cOff * 256, MBBufAlpha, oO); + + pSCEnc->m_pNextSC->MBInfo.iQIndexLP = pMBInfoAlpha[cOff].iQIndexLP; + pSCEnc->m_pNextSC->MBInfo.iQIndexHP = pMBInfoAlpha[cOff].iQIndexHP; + + if(encodeMB(pSCEnc->m_pNextSC, cColumn, cRow) != ICERR_OK) + return ICERR_ERROR; + } + } + + advanceOneMBRow(pSCEnc); + } + } + + free(pMBBuf); + if(oO != O_NONE){ + free(pFrameBuf); + free(pMBInfo); + if(pParam->uAlphaMode > 0){ // alpha channel + free(pFrameBufAlpha); + free(pMBInfoAlpha); + } + } + + freePredInfo(pSCDec); + freeTileInfo(pSCDec); + StrIODecTerm(pSCDec); + FreeCodingContextDec(pSCDec); + if(pSCDec->m_param.bAlphaChannel) + free(pSCDec->m_pNextSC); + free(pSCDec); + free(pIOHeaderDec); + + if(pParam->bIgnoreOverlap == FALSE){ + freePredInfo(pSCEnc); + freeTileInfo(pSCEnc); + StrIOEncTerm(pSCEnc); + free(pTileQPInfo); + FreeCodingContextEnc(pSCEnc); + } + free(pSCEnc); + free(pIOHeaderEnc); + + return ICERR_OK; +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/JXRTranscode.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/JXRTranscode.o new file mode 100644 index 0000000..ce1a1b5 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/JXRTranscode.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.c new file mode 100644 index 0000000..dcaea49 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.c @@ -0,0 +1,200 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +/****************************************************************************** + +Module Name: + decode.c + +Abstract: + Defines the entry point for the console application. + +Author: + +Revision History: +*******************************************************************************/ +#include "strcodec.h" +#include "decode.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +/****************************************************************** +Free Adaptive Huffman Table +******************************************************************/ +static Void CleanAH(CAdaptiveHuffman **ppAdHuff) +{ + CAdaptiveHuffman *pAdHuff; + + if (NULL != ppAdHuff) { + pAdHuff = *ppAdHuff; + if (NULL != pAdHuff) { + free(pAdHuff); + } + *ppAdHuff = NULL; + } +} + +static Void CleanAHDec(CCodingContext * pSC) +{ + Int kk; + + for (kk = 0; kk < NUMVLCTABLES; kk++) { + CleanAH(&(pSC->m_pAHexpt[kk])); + } + CleanAH(&(pSC->m_pAdaptHuffCBPCY)); + CleanAH(&(pSC->m_pAdaptHuffCBPCY1)); +} + +/************************************************************************* + Initialize an adaptive huffman table +*************************************************************************/ +static Int InitializeAH(CAdaptiveHuffman **ppAdHuff, Int iSym) +{ + Int iMemStatus = 0; + + CAdaptiveHuffman *pAdHuff = Allocate(iSym, DECODER); + if (pAdHuff == NULL) { + iMemStatus = -1; // out of memory + goto ErrorExit; + } + + //Adapt(pAdHuff, bFixedTables); + //InitHuffman(pAdHuff->m_pHuffman); + //if (ICERR_OK != initHuff(pAdHuff->m_pHuffman, 1, pAdHuff->m_pTable, NULL)) { + // goto ErrorExit; + //} + *ppAdHuff = pAdHuff; + return ICERR_OK; + +ErrorExit: + if (pAdHuff) { + free(pAdHuff); + } + *ppAdHuff = NULL; + if (-1 == iMemStatus) { + printf("Insufficient memory to init decoder.\n"); + } + return ICERR_ERROR; +} + + +/************************************************************************* + Context allocation +*************************************************************************/ +Int AllocateCodingContextDec(CWMImageStrCodec *pSC, Int iNumContexts) +{ + Int i, iCBPSize, k; + static const Int aAlphabet[] = {5,4,8,7,7, 12,6,6,12,6,6,7,7, 12,6,6,12,6,6,7,7}; + + if (iNumContexts > MAX_TILES || iNumContexts < 1) // only between 1 and MAX_TILES allowed + return ICERR_ERROR; + + if (pSC == NULL) + return ICERR_ERROR; + + pSC->m_pCodingContext = malloc (iNumContexts * sizeof (CCodingContext)); + if (pSC->m_pCodingContext == NULL) { + pSC->cNumCodingContext = 0; + return ICERR_ERROR; + } + memset (pSC->m_pCodingContext, 0, iNumContexts * sizeof (CCodingContext)); + + pSC->cNumCodingContext = iNumContexts; + iCBPSize = (pSC->m_param.cfColorFormat == Y_ONLY || pSC->m_param.cfColorFormat == NCOMPONENT + || pSC->m_param.cfColorFormat == CMYK) ? 5 : 9; + + /** allocate / initialize members **/ + for (i = 0; i < iNumContexts; i++) { + CCodingContext *pContext = &(pSC->m_pCodingContext[i]); + + /** allocate adaptive Huffman encoder **/ + if (InitializeAH(&pContext->m_pAdaptHuffCBPCY, iCBPSize) != ICERR_OK) { + return ICERR_ERROR; + } + if (InitializeAH(&pContext->m_pAdaptHuffCBPCY1, 5) != ICERR_OK) { + return ICERR_ERROR; + } + + for(k = 0; k < NUMVLCTABLES; k ++){ + if (InitializeAH(&pContext->m_pAHexpt[k], aAlphabet[k]) != ICERR_OK) { + return ICERR_ERROR; + } + } + + ResetCodingContextDec(pContext); + } + + return ICERR_OK; +} + +/************************************************************************* + Context reset on encoder +*************************************************************************/ +Void ResetCodingContextDec(CCodingContext *pContext) +{ + Int k; + /** set flags **/ + pContext->m_pAdaptHuffCBPCY->m_bInitialize = FALSE; + pContext->m_pAdaptHuffCBPCY1->m_bInitialize = FALSE; + for(k = 0; k < NUMVLCTABLES; k ++) + pContext->m_pAHexpt[k]->m_bInitialize = FALSE; + + // reset VLC tables + AdaptLowpassDec (pContext); + AdaptHighpassDec (pContext); + + // reset zigzag patterns, totals + InitZigzagScan(pContext); + // reset bit reduction and cbp models + ResetCodingContext(pContext); +} + +/************************************************************************* + Context deletion +*************************************************************************/ +Void FreeCodingContextDec(CWMImageStrCodec *pSC) +{ + Int iContexts = (Int)(pSC->cNumCodingContext), i, k; + + if (iContexts > 0 && pSC->m_pCodingContext) { + + for (i = 0; i < iContexts; i++) { + CCodingContext *pContext = &(pSC->m_pCodingContext[i]); + CleanAH (&pContext->m_pAdaptHuffCBPCY); + CleanAH (&pContext->m_pAdaptHuffCBPCY1); + for (k = 0; k < NUMVLCTABLES; k++) + CleanAH (&pContext->m_pAHexpt[k]); + } + free (pSC->m_pCodingContext); + } +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.h new file mode 100644 index 0000000..44c12e4 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.h @@ -0,0 +1,143 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#ifndef WMI_DECODE_H +#define WMI_DECODE_H + +typedef struct CWMDecoderParameters { + /** ROI decode **/ + Bool bDecodeFullFrame; + Bool bDecodeFullWidth; + + /** thumbnail decode **/ + Bool bSkipFlexbits; + size_t cThumbnailScale; // 1: cThumbnailScale thumbnail, only supports cThumbnailScale = 2^m for now + Bool bDecodeHP; + Bool bDecodeLP; + + // Region of interest decoding + size_t cROILeftX; + size_t cROIRightX; + size_t cROITopY; + size_t cROIBottomY; + + // table lookups for rotation and flip + size_t * pOffsetX; + size_t * pOffsetY; +} CWMDecoderParameters; + +Void predCBPDec(CWMImageStrCodec *, CCodingContext *); +Void predDCACDec(CWMImageStrCodec *); +Void predACDec(CWMImageStrCodec *); + +Int dequantizeMacroblock(CWMImageStrCodec *); +Int invTransformMacroblock(CWMImageStrCodec * pSC); +Int invTransformMacroblock_alteredOperators_hard(CWMImageStrCodec * pSC); + +Int DecodeMacroblockDC(CWMImageStrCodec * pSC, CCodingContext *pContext, Int iMBX, Int iMBY); +Int DecodeMacroblockLowpass(CWMImageStrCodec * pSC, CCodingContext *pContext, Int iMBX, Int iMBY); +Int DecodeMacroblockHighpass(CWMImageStrCodec * pSC, CCodingContext *pContext, Int iMBX, Int iMBY); + +Int AdaptLowpassDec(struct CCodingContext *); +Int AdaptHighpassDec(struct CCodingContext *); + +Void ResetCodingContextDec(CCodingContext *pContext); +Void FreeCodingContextDec(struct CWMImageStrCodec *pSC); + +/*************************************************************************/ +// Inverse transform functions +// 2-point post filter for boundaries (only used in 420 UV DC subband) +Void strPost2(PixelI *, PixelI *); + +// 2x2 post filter (only used in 420 UV DC subband) +Void strPost2x2(PixelI *, PixelI *, PixelI *, PixelI *); + +/** 4-point post filter for boundaries **/ +Void strPost4(PixelI *, PixelI *, PixelI *, PixelI *); + +/** data allocation in working buffer (first stage) **/ + +/** Y, 444 U and V **/ +/** 0 1 2 3 **/ +/** 32 33 34 35 **/ +/** 64 65 66 67 **/ +/** 96 97 98 99 **/ + +/** 420 U and V **/ +/** 0 2 4 6 **/ +/** 64 66 68 70 **/ +/** 128 130 132 134 **/ +/** 192 194 196 198 **/ + +/** 4x4 inverse DCT for first stage **/ +Void strIDCT4x4FirstStage(PixelI *); +Void strIDCT4x4Stage1(PixelI*); +Void strIDCT4x4FirstStage420UV(PixelI *); + +/** 4x4 post filter for first stage **/ +Void strPost4x4FirstStage(PixelI *); +Void strPost4x4Stage1Split(PixelI*, PixelI*, Int, Int, Bool); +Void strPost4x4Stage1(PixelI*, Int, Int, Bool); +Void strPost4x4Stage1Split_alternate(PixelI*, PixelI*, Int); +Void strPost4x4Stage1_alternate(PixelI*, Int); +//Void strPost4x4Stage1Split_420(PixelI*, PixelI*); +//Void strPost4x4Stage1_420(PixelI*); + +Void strPost4x4FirstStage420UV(PixelI *); + +/** data allocation in working buffer (second stage)**/ + +/** Y, 444 U and V **/ +/** 0 4 8 12 **/ +/** 128 132 136 140 **/ +/** 256 260 264 268 **/ +/** 384 388 392 396 **/ + +/** 420 U and V **/ +/** 0 8 **/ +/** 256 264 **/ + +/** 4x4 invesr DCT for second stage **/ +//Void strIDCT4x4SecondStage(PixelI *); +Void strIDCT4x4Stage2(PixelI*); +Void strNormalizeDec(PixelI*, Bool); +Void strDCT2x2dnDec(PixelI *, PixelI *, PixelI *, PixelI *); + +/** 4x4 post filter for second stage **/ +Void strPost4x4SecondStage(PixelI *); +Void strPost4x4Stage2Split(PixelI*, PixelI*); +Void strPost4x4Stage2Split_alternate(PixelI*, PixelI*); + +/** Huffman decode related defines **/ +#define HUFFMAN_DECODE_ROOT_BITS_LOG 3 +#define HUFFMAN_DECODE_ROOT_BITS (5) + +Int getHuff(const short *pDecodeTable, BitIOInfo* pIO); + +#endif // WMI_DECODE_H + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.o new file mode 100644 index 0000000..27df9d7 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/decode.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/postprocess.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/postprocess.c new file mode 100644 index 0000000..e58bd6e --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/postprocess.c @@ -0,0 +1,288 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "windowsmediaphoto.h" +#include "strcodec.h" + +Void smoothMB(PixelI * p1, PixelI * p0, PixelI * q0, PixelI * q1) +{ + // p1 p0 | q0 q1 + PixelI delta = ((((*q0 - *p0) << 2) + (*p1 - *q1)) >> 3); + + *q0 -= delta; + *p0 += delta; +} + +Void smooth(PixelI * p2, PixelI * p1, PixelI * p0, PixelI * q0, PixelI * q1, PixelI * q2) +{ + // p2 p1 p0 | q0 q1 q2 + PixelI delta = ((((*q0 - *p0) << 2) + (*p1 - *q1)) >> 3); + + *q0 -= delta; + *p0 += delta; + + *p1 = (*p1 >> 1) + ((*p0 + *p2) >> 2); + *q1 = (*q1 >> 1) + ((*q0 + *q2) >> 2); +} + +Int initPostProc(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], size_t mbWidth, size_t iNumChannels) +{ + size_t i, j, k, l; + Bool b32bit = sizeof(int) == 4; + + for(j = 0; j < iNumChannels; j ++){ + for(i = 0; i < 2; i ++){ + // 2 more are allocated to avoid boundary check + if(b32bit) // integer overlow/underflow check for 32-bit system + if((((mbWidth + 2) >> 16) * sizeof(struct tagPostProcInfo)) & 0xffff0000) + return ICERR_ERROR; + strPostProcInfo[j][i] = (struct tagPostProcInfo *)malloc((mbWidth + 2) * sizeof(struct tagPostProcInfo)); + assert(strPostProcInfo[j][i] != NULL); + if(strPostProcInfo[j][i] == NULL){ + return ICERR_ERROR; + } + strPostProcInfo[j][i] ++; + + // initialize out-of-bound MBs as bumpy (no post at all) to avoid boundary check + // left boundary + strPostProcInfo[j][i][-1].ucMBTexture = 3; + for(l = 0; l < 4; l ++){ + for(k = 0; k < 4; k ++){ + strPostProcInfo[j][i][-1].ucBlockTexture[l][k] = 3; + } + } + // right boundary + strPostProcInfo[j][i][mbWidth] = strPostProcInfo[j][i][-1]; + } + } + + return ICERR_OK; +} + +Void termPostProc(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], size_t iNumChannels) +{ + size_t i, j; + + for(j = 0; j < iNumChannels; j ++){ + for(i = 0; i < 2; i ++){ + if(strPostProcInfo[j][i] != NULL){ + free(strPostProcInfo[j][i] - 1); + } + } + } +} + +Void slideOneMBRow(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], size_t iNumChannels, size_t mbWidth, Bool top, Bool bottom) +{ + size_t i, j; + struct tagPostProcInfo * bar; + + for(i = 0; i < iNumChannels; i ++){ + // swap previous row and current row + bar = strPostProcInfo[i][0]; + strPostProcInfo[i][0] = strPostProcInfo[i][1]; + strPostProcInfo[i][1] = bar; + + if(top){ // if top row, previous row is out of boundary + for(j = 0; j < mbWidth; j ++){ + strPostProcInfo[i][0][j] = strPostProcInfo[i][0][-1]; // set as bumpy + } + } + + if(bottom){ // if bottom bottom row, set current row of MBs (out of boundary) as bumpy + for(j = 0; j < mbWidth; j ++){ + strPostProcInfo[i][1][j] = strPostProcInfo[i][1][-1]; // set as bumpy + } + } + } +} + +// get DC and texture infomation right before transform +Void updatePostProcInfo(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], PixelI * pMB, size_t mbX, size_t cc) +{ + size_t i, j; + struct tagPostProcInfo * pMBInfo = strPostProcInfo[cc][1] + mbX; + + // DC of MB + pMBInfo->iMBDC = pMB[0]; + + // texture of MB + pMBInfo->ucMBTexture = 0; // smooth + for(i = 16; i < 256; i += 16){ + if(pMB[i] != 0){ + pMBInfo->ucMBTexture = 3; // bumpy + break; + } + } + + // DCs of blocks not available yet, will collect after demacroblocking + + // textures of blocks + for(j = 0; j < 4; j ++) + for(i = 0; i < 4; i ++){ + PixelI * p = pMB + i * 64 + j * 16; + size_t k; + + for(k = 1, pMBInfo->ucBlockTexture[j][i] = 0; k < 16; k ++){ + if(p[k] != 0){ + pMBInfo->ucBlockTexture[j][i] = 3; + break; + } + } + } +} + +// demacroblock critirion: two MBs have same texture other than bumpy and DCs differ less than 1 +#define DMB(a, b) (a->ucMBTexture + b->ucMBTexture == 0) && (abs(a->iMBDC - b->iMBDC) <= threshold) + +// demacroblock and get DCs of blocks +Void postProcMB(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], PixelI * p0, PixelI * p1, size_t mbX, size_t cc, Int threshold) +{ + /* 4 MBs involved, current MB is d, we have 4 2-pixel boundary segments */ + /* | */ + /* a | b */ + /* - - + + */ + /* c ! d */ + /* ! */ + struct tagPostProcInfo * pMBb = strPostProcInfo[cc][0] + mbX, * pMBa = pMBb - 1, * pMBd = strPostProcInfo[cc][1] + mbX, * pMBc = pMBd - 1; + + // demacroblock segment -- + if(DMB(pMBa, pMBc)){ + smoothMB(p0 - 256 + 10 * 16, p0 - 256 + 11 * 16, p1 - 256 + 8 * 16, p1 - 256 + 9 * 16); + smoothMB(p0 - 256 + 14 * 16, p0 - 256 + 15 * 16, p1 - 256 + 12 * 16, p1 - 256 + 13 * 16); + } + + // demacroblock segment ++ + if(DMB(pMBb, pMBd)){ + smoothMB(p0 + 2 * 16, p0 + 3 * 16, p1 + 0 * 16, p1 + 1 * 16); + smoothMB(p0 + 6 * 16, p0 + 7 * 16, p1 + 4 * 16, p1 + 5 * 16); + } + + // demacroblock segment | + if(DMB(pMBa, pMBb)){ + smoothMB(p0 - 256 + 10 * 16, p0 - 256 + 14 * 16, p0 + 2 * 16, p0 + 6 * 16); + smoothMB(p0 - 256 + 11 * 16, p0 - 256 + 15 * 16, p0 + 3 * 16, p0 + 7 * 16); + } + + // demacroblock segment ! + if(DMB(pMBc, pMBd)){ + smoothMB(p1 - 256 + 8 * 16, p1 - 256 + 12 * 16, p1 + 0 * 16, p1 + 4 * 16); + smoothMB(p1 - 256 + 9 * 16, p1 - 256 + 13 * 16, p1 + 1 * 16, p1 + 5 * 16); + } + + /* update DCs of blocks */ + // MB d + pMBd->iBlockDC[0][0] = p1[0 * 16]; + pMBd->iBlockDC[0][1] = p1[4 * 16]; + pMBd->iBlockDC[1][0] = p1[1 * 16]; + pMBd->iBlockDC[1][1] = p1[5 * 16]; + + // MB b + pMBb->iBlockDC[2][0] = p0[2 * 16]; + pMBb->iBlockDC[2][1] = p0[6 * 16]; + pMBb->iBlockDC[3][0] = p0[3 * 16]; + pMBb->iBlockDC[3][1] = p0[7 * 16]; + + // MB c + pMBc->iBlockDC[0][2] = p1[ 8 * 16 - 256]; + pMBc->iBlockDC[0][3] = p1[12 * 16 - 256]; + pMBc->iBlockDC[1][2] = p1[ 9 * 16 - 256]; + pMBc->iBlockDC[1][3] = p1[13 * 16 - 256]; + + // MB a + pMBa->iBlockDC[2][2] = p0[10 * 16 - 256]; + pMBa->iBlockDC[2][3] = p0[14 * 16 - 256]; + pMBa->iBlockDC[3][2] = p0[11 * 16 - 256]; + pMBa->iBlockDC[3][3] = p0[15 * 16 - 256]; +} + +/* deblock and destair blocks */ +/* 4 MBs involved, need to process 16 blocks of a */ +/* | */ +/* a | b */ +/* - - - - */ +/* c | d */ +/* | */ +Void postProcBlock(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], PixelI * p0, PixelI * p1, size_t mbX, size_t cc, Int threshold) +{ + size_t i, j, k; + Int dc[5][5]; + U8 texture[5][5]; + struct tagPostProcInfo * pMBb = strPostProcInfo[cc][0] + mbX, * pMBa = pMBb - 1, * pMBd = strPostProcInfo[cc][1] + mbX, * pMBc = pMBd - 1; + PixelI * pc, * pt; + + /* copy DC and Texture info, can be optimized out */ + for(j = 0; j < 4; j ++){ + // from MB a + for(i = 0; i < 4; i ++){ + dc[j][i] = pMBa->iBlockDC[j][i]; + texture[j][i] = pMBa->ucBlockTexture[j][i]; + } + + // 4 blocks from MB c + dc[4][j] = pMBc->iBlockDC[0][j]; + texture[4][j] = pMBc->ucBlockTexture[0][j]; + + // 4 blocks from MB b + dc[j][4] = pMBb->iBlockDC[j][0]; + texture[j][4] = pMBb->ucBlockTexture[j][0]; + } + // 1 block from MB d + dc[4][4] = pMBd->iBlockDC[0][0]; + texture[4][4] = pMBd->ucBlockTexture[0][0]; + + /* block boundaries */ + /* | */ + /* | */ + /* --- */ + + for(j = 0; j < 4; j ++){ + for(i = 0; i < 4; i ++){ + pc = p0 - 256 + i * 64 + j * 16; + + // deblock + if(texture[j][i] + texture[j + 1][i] < 3 && abs(dc[j][i] - dc[j + 1][i]) <= threshold){ + // smooth horizontal boundary ---- + pt = (j < 3 ? pc + 16 : p1 - 256 + i * 64); + for(k = 0; k < 4; k ++){ + smooth(pc + idxCC[1][k], pc + idxCC[2][k], pc + idxCC[3][k], pt + idxCC[0][k], pt + idxCC[1][k], pt + idxCC[2][k]); + } + } + + // two horizontally adjacent blocks have same texture and similiar DCs + if(texture[j][i] + texture[j][i + 1] < 3 && abs(dc[j][i] - dc[j][i + 1]) <= threshold){ + // smooth vertical boundary | + pt = pc + 64; + for(k = 0; k < 4; k ++){ + smooth(pc + idxCC[k][1], pc + idxCC[k][2], pc + idxCC[k][3], pt + idxCC[k][0], pt + idxCC[k][1], pt + idxCC[k][2]); + } + } + } + } +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/postprocess.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/postprocess.o new file mode 100644 index 0000000..40cc073 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/postprocess.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/segdec.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/segdec.c new file mode 100644 index 0000000..312a5bf --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/segdec.c @@ -0,0 +1,1205 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strcodec.h" +#include "decode.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +extern const int dctIndex[3][16]; +extern const int blkOffset[16]; +extern const int blkOffsetUV[4]; +static Int DecodeSignificantAbsLevel (struct CAdaptiveHuffman *pAHexpt, BitIOInfo* pIO); + +//#undef X86OPT_INLINE + +#ifdef X86OPT_INLINE +#define _FORCEINLINE __forceinline +#else // X86OPT_INLINE +#define _FORCEINLINE +#endif // X86OPT_INLINE + +//================================================================ +// Memory access functions +//================================================================ +static U32 _FORCEINLINE _load4(void* pv) +{ +#ifdef _BIG__ENDIAN_ + return (*(U32*)pv); +#else // _BIG__ENDIAN_ +#if defined(_M_IA64) || defined(_ARM_) + U32 v; + v = ((U16 *) pv)[0]; + v |= ((U32)((U16 *) pv)[1]) << 16; + return _byteswap_ulong(v); +#else // _M_IA64 + return _byteswap_ulong(*(U32*)pv); +#endif // _M_IA64 +#endif // _BIG__ENDIAN_ +} + +static _FORCEINLINE U32 _peekBit16(BitIOInfo* pIO, U32 cBits) +{ + PEEKBIT16(pIO, cBits); + // masking is not needed here because shift of unsigned int is implemented as a logical shift (SHR)! +} + +#define LOAD16 _load4 +static _FORCEINLINE U32 _flushBit16(BitIOInfo* pIO, U32 cBits) +{ + FLUSHBIT16(pIO, cBits); +} + +static _FORCEINLINE U32 _getBit16(BitIOInfo* pIO, U32 cBits) +{ + U32 uiRet = _peekBit16(pIO, cBits); + _flushBit16(pIO, cBits); + + return uiRet; +} + +#define SIGN_BIT(TypeOrValue) (((UInt) 1) << (8 * sizeof (TypeOrValue) - 1)) +/*********************************************************************************************************** + Huffman decode (input is a fully built Huffman table) +***********************************************************************************************************/ +Int getHuff(const short *pDecodeTable, BitIOInfo* pIO) +{ + Int iSymbol, iSymbolHuff; + iSymbol = pDecodeTable[peekBit16(pIO, HUFFMAN_DECODE_ROOT_BITS)]; + + flushBit16(pIO, iSymbol < 0 ? HUFFMAN_DECODE_ROOT_BITS : iSymbol & ((1 << HUFFMAN_DECODE_ROOT_BITS_LOG) - 1)); + iSymbolHuff = iSymbol >> HUFFMAN_DECODE_ROOT_BITS_LOG; + + if (iSymbolHuff < 0) { + iSymbolHuff = iSymbol; + while ((iSymbolHuff = pDecodeTable[iSymbolHuff + SIGN_BIT (pDecodeTable[0]) + getBit16(pIO, 1)]) < 0); + } + return (iSymbolHuff); +} + +#if 1 +static _FORCEINLINE U32 _getBool16(BitIOInfo* pIO) +{ + U32 uiRet = pIO->uiAccumulator >> 31;//_peekBit16(pIO, 1); + //_flushBit16(pIO, 1); + pIO->cBitsUsed++; + if (pIO->cBitsUsed < 16) { + pIO->uiAccumulator <<= 1; + } + else { + pIO->pbCurrent = MASKPTR(pIO->pbCurrent + ((pIO->cBitsUsed >> 3)/* & 2*/), pIO->iMask); + pIO->cBitsUsed &= 16 - 1; + pIO->uiAccumulator = LOAD16(pIO->pbCurrent) << pIO->cBitsUsed; + } + + return uiRet; +} + +static _FORCEINLINE I32 _getSign(BitIOInfo* pIO) +{ + I32 uiRet = (int) pIO->uiAccumulator >> 31;//_peekBit16(pIO, 1); + //_flushBit16(pIO, 1); + pIO->cBitsUsed++; + if (pIO->cBitsUsed < 16) { + pIO->uiAccumulator <<= 1; + } + else { + pIO->pbCurrent = MASKPTR(pIO->pbCurrent + ((pIO->cBitsUsed >> 3)/* & 2*/), pIO->iMask); + pIO->cBitsUsed &= 16 - 1; + pIO->uiAccumulator = LOAD16(pIO->pbCurrent) << pIO->cBitsUsed; + } + + return uiRet; +} +#else +#define _getBool16(x) _getBit16((x),1) +#define _getSign(x) (-_getBit16((x),1)) +#endif + +/** this function returns cBits if zero is read, or a signed value if first cBits are not all zero **/ +static _FORCEINLINE I32 _getBit16s(BitIOInfo* pIO, U32 cBits) +{ + I32 iRet = (I32)_peekBit16(pIO, cBits + 1); + iRet = ((iRet >> 1) ^ (-(iRet & 1))) + (iRet & 1); + _flushBit16(pIO, cBits + (iRet != 0)); + return iRet; +} + +/************************************************************************* + Huffman decoding with short tables +*************************************************************************/ +static _FORCEINLINE Int _getHuffShort(const short *pDecodeTable, BitIOInfo* pIO) +{ + Int iSymbol = pDecodeTable[_peekBit16(pIO, HUFFMAN_DECODE_ROOT_BITS)]; + assert(iSymbol >= 0); + // for some strange reason, inlining flushBit doesn't work well + flushBit16(pIO, iSymbol & ((1 << HUFFMAN_DECODE_ROOT_BITS_LOG) - 1)); + return (iSymbol >> HUFFMAN_DECODE_ROOT_BITS_LOG); +} +/************************************************************************* + Adapt + Huffman init +*************************************************************************/ +static Int AdaptDecFixed (CAdaptiveHuffman *pAH) +{ + AdaptDiscriminant (pAH); + return ICERR_OK; +} + +/************************************************************************* + DecodeCBP +*************************************************************************/ +static Void DecodeCBP(CWMImageStrCodec * pSC, CCodingContext *pContext) +{ + BitIOInfo* pIO = pContext->m_pIOAC; + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannel = (cf == NCOMPONENT || cf == CMYK) ? (Int) pSC->m_param.cNumChannels : 1; + Int iCBPCY, iCBPCU , iCBPCV; + Int k, iBlock, i; + Int iNumCBP; + Bool bIsChroma; + CAdaptiveHuffman *pAHCBP = pContext->m_pAdaptHuffCBPCY; + CAdaptiveHuffman *pAHCBP1 = pContext->m_pAdaptHuffCBPCY1; + CAdaptiveHuffman *pAHex1 = pContext->m_pAHexpt[1]; + + readIS_L1(pSC, pIO); + + for (i = 0; i < iChannel; i++) { + + iCBPCY = iCBPCU = iCBPCV = 0; + iNumCBP = _getHuffShort(pAHCBP1->m_hufDecTable, pIO); + pAHCBP1->m_iDiscriminant += pAHCBP1->m_pDelta[iNumCBP]; + + switch (iNumCBP) { + case 2: + iNumCBP = _getBit16(pIO, 2); + if (iNumCBP == 0) + iNumCBP = 3; + else if (iNumCBP == 1) + iNumCBP = 5; + else { + static const Int aTab[] = { 6, 9, 10, 12 }; + iNumCBP = aTab[iNumCBP * 2 + _getBool16 (pIO) - 4]; + } + break; + case 1: + iNumCBP = 1 << _getBit16(pIO, 2); + break; + case 3: + iNumCBP = 0xf ^ (1 << _getBit16(pIO, 2)); + break; + case 4: + iNumCBP = 0xf; + } + + for (iBlock = 0; iBlock < 4; iBlock++) { + if (iNumCBP & (1 << iBlock)) { + static const UInt gFLC0[] = { 0,2,1,2,2,0 }; + static const UInt gOff0[] = { 0,4,2,8,12,1 }; + static const UInt gOut0[] = { 0,15,3,12, 1,2,4,8, 5,6,9,10, 7,11,13,14 }; + Int iNumBlockCBP = getHuff(pAHCBP->m_hufDecTable, pIO); + unsigned int val = (unsigned int) iNumBlockCBP + 1, iCode1; + + pAHCBP->m_iDiscriminant += pAHCBP->m_pDelta[iNumBlockCBP]; + iNumBlockCBP = 0; + + if (val >= 6) { // chroma present + if (_getBool16 (pIO)) { + iNumBlockCBP = 0x10; + } + else if (_getBool16 (pIO)) { + iNumBlockCBP = 0x20; + } + else { + iNumBlockCBP = 0x30; + } + if (val == 9) { + if (_getBool16 (pIO)) { + // do nothing + } + else if (_getBool16 (pIO)) { + val = 10; + } + else { + val = 11; + } + } + val -= 6; + } + iCode1 = gOff0[val]; + if (gFLC0[val]) { + iCode1 += _getBit16(pIO, gFLC0[val]); + } + iNumBlockCBP += gOut0[iCode1]; + + switch (cf) { + case YUV_444: + iCBPCY |= ((iNumBlockCBP & 0xf) << (iBlock * 4)); + for (k = 0; k < 2; k++) { + bIsChroma = ((iNumBlockCBP>>(k+4)) & 0x01); + if (bIsChroma) { // U is present in block + Int iCode = _getHuffShort(pAHex1->m_hufDecTable, pIO); + switch (iCode) { + case 1: + iCode = _getBit16(pIO, 2); + if (iCode == 0) + iCode = 3; + else if (iCode == 1) + iCode = 5; + else { + static const Int aTab[] = { 6, 9, 10, 12 }; + iCode = aTab[iCode * 2 + _getBool16 (pIO) - 4]; + } + break; + case 0: + iCode = 1 << _getBit16(pIO, 2); + break; + case 2: + iCode = 0xf ^ (1 << _getBit16(pIO, 2)); + break; + case 3: + iCode = 0xf; + } + if (k == 0) + iCBPCU |= (iCode << (iBlock * 4)); + else + iCBPCV |= (iCode << (iBlock * 4)); + } + } + break; + + case YUV_420: + iCBPCY |= ((iNumBlockCBP & 0xf) << (iBlock * 4)); + iCBPCU |= ((iNumBlockCBP >> 4) & 0x1) << (iBlock); + iCBPCV |= ((iNumBlockCBP >> 5) & 0x1) << (iBlock); + break; + + case YUV_422: + iCBPCY |= ((iNumBlockCBP & 0xf) << (iBlock * 4)); + for (k = 0; k < 2; k ++) { + Int iCode = 5; + const Int iShift[4] = {0, 1, 4, 5}; + if((iNumBlockCBP >> (k + 4)) & 0x01) { + if(_getBool16(pIO)) { + iCode = 1; + } + else if(_getBool16(pIO)){ + iCode = 4; + } + iCode <<= iShift[iBlock]; + if(k == 0) iCBPCU |= iCode; + else iCBPCV |= iCode; + } + } + break; + + default: + iCBPCY |= (iNumBlockCBP << (iBlock * 4)); + } + } + } + + pSC->MBInfo.iDiffCBP[i] = iCBPCY; + if (cf == YUV_420 || cf == YUV_444 || cf == YUV_422) { + pSC->MBInfo.iDiffCBP[1] = iCBPCU; + pSC->MBInfo.iDiffCBP[2] = iCBPCV; + } + } +} + +/************************************************************************* + Experimental code -- decodeBlock + SR = <0 1 2> == + alphabet 12: + pAHexpt[0] == + alphabet 6: + pAHexpt[1] == + pAHexpt[2] == + alphabet 4: + pAHexpt[3] == (SR may be last or insignificant only) + alphabet f(run) (this can be extended to 6 contexts - SL and SR') + pAHexpt[4] == + alphabet f(lev) (this can be extended to 9 contexts) + pAHexpt[5-6] == first symbol + pAHexpt[7-8] == condition on SRn no use +*************************************************************************/ + +Int _FORCEINLINE DecodeSignificantRun (Int iMaxRun, struct CAdaptiveHuffman *pAHexpt, BitIOInfo* pIO) +{ + Int iIndex; + static const Int aRemap[] = {1,2,3,5,7, 1,2,3,5,7, /*1,2,3,4,6, */1,2,3,4,5 }; + Int iBin = gSignificantRunBin[iMaxRun]; + Int iRun = 0, iFLC = 0; + + if (iMaxRun < 5) { + if (iMaxRun == 1) { + return 1; + } + else if (_getBool16 (pIO)) { + return 1; + } + else if (iMaxRun == 2 || _getBool16 (pIO)) { + return 2; + } + else if (iMaxRun == 3 || _getBool16 (pIO)) { + return 3; + } + return 4; + } + iIndex = _getHuffShort (pAHexpt->m_hufDecTable, pIO); + iIndex += iBin * 5; + iRun = aRemap[iIndex]; + iFLC = gSignificantRunFixedLength[iIndex]; + if (iFLC) { + iRun += _getBit16 (pIO, iFLC); + } + return iRun; +} + +#ifndef X86OPT_INLINE +static Void DecodeFirstIndex (Int *pIndex, struct CAdaptiveHuffman *pAHexpt, + BitIOInfo* pIO) +#else +static __forceinline Void DecodeFirstIndex (Int *pIndex, struct CAdaptiveHuffman *pAHexpt, + BitIOInfo* pIO) +#endif +{ + Int iIndex; + iIndex = getHuff (pAHexpt->m_hufDecTable, pIO); + pAHexpt->m_iDiscriminant += pAHexpt->m_pDelta[iIndex]; + pAHexpt->m_iDiscriminant1 += pAHexpt->m_pDelta1[iIndex]; + *pIndex = iIndex; +} + +#ifndef X86OPT_INLINE +static Void DecodeIndex (Int *pIndex, Int iLoc, struct CAdaptiveHuffman *pAHexpt, + BitIOInfo* pIO) +#else +static __forceinline Void DecodeIndex (Int *pIndex, Int iLoc, + struct CAdaptiveHuffman *pAHexpt, BitIOInfo* pIO) +#endif +{ + Int iIndex; + if (iLoc < 15) { + iIndex = _getHuffShort (pAHexpt->m_hufDecTable, pIO); + pAHexpt->m_iDiscriminant += pAHexpt->m_pDelta[iIndex]; + pAHexpt->m_iDiscriminant1 += pAHexpt->m_pDelta1[iIndex]; + *pIndex = iIndex; + } + else if (iLoc == 15) { + if (_getBool16 (pIO) == 0) { + iIndex = 0; + } + else if (_getBool16 (pIO) == 0) { + iIndex = 2; + } + else { + iIndex = 1 + 2 * _getBool16 (pIO); + } + *pIndex = iIndex; + } + else { //if (iLoc == 16) { /* deterministic */ + Int iSL = _getBit16 (pIO, 1/* + 1*/); + *pIndex = iSL;// >> 1; + } +} + +static _FORCEINLINE Int DecodeBlock (Bool bChroma, Int *aLocalCoef, struct CAdaptiveHuffman **pAHexpt, + const Int iContextOffset, BitIOInfo* pIO, Int iLocation) +{ + Int iSR, iSRn, iIndex, iNumNonzero = 1, iCont, iSign; + struct CAdaptiveHuffman **pAH1 = pAHexpt + iContextOffset + bChroma * 3; + + /** first symbol **/ + DecodeFirstIndex (&iIndex, /*&iSign, */pAH1[0], pIO); + iSR = (iIndex & 1); + iSRn = iIndex >> 2; + + iCont = iSR & iSRn; + iSign = _getSign(pIO); + + if (iIndex & 2 /* iSL */) { + aLocalCoef[1] = (DecodeSignificantAbsLevel (pAHexpt[6 + iContextOffset + iCont], pIO) ^ iSign) - iSign; + } + else { + aLocalCoef[1] = (1 | iSign); // 0 -> 1; -1 -> -1 + } + aLocalCoef[0] = 0; + if (iSR == 0) { + aLocalCoef[0] = DecodeSignificantRun (15 - iLocation, pAHexpt[0], pIO); + } + iLocation += aLocalCoef[0] + 1; + + while (iSRn != 0) { + iSR = iSRn & 1; + aLocalCoef[iNumNonzero * 2] = 0; + if (iSR == 0) { + aLocalCoef[iNumNonzero * 2] = DecodeSignificantRun (15 - iLocation, pAHexpt[0], pIO); + } + iLocation += aLocalCoef[iNumNonzero * 2] + 1; + DecodeIndex (&iIndex, /*&iSign, */iLocation, pAH1[iCont + 1], pIO); + iSRn = iIndex >> 1; + + assert (iSRn >= 0 && iSRn < 3); + iCont &= iSRn; /** huge difference! **/ + iSign = _getSign(pIO); + + if (iIndex & 1 /* iSL */) { + aLocalCoef[iNumNonzero * 2 + 1] = + (DecodeSignificantAbsLevel (pAHexpt[6 + iContextOffset + iCont], pIO) ^ iSign) - iSign; + } + else { + aLocalCoef[iNumNonzero * 2 + 1] = (1 | iSign); // 0 -> 1; -1 -> -1 (was 1 + (iSign * 2)) + } + iNumNonzero++; + } + return iNumNonzero; +} + +/************************************************************************* + DecodeBlockHighpass : +*************************************************************************/ +static _FORCEINLINE Int DecodeBlockHighpass (const Bool bChroma, struct CAdaptiveHuffman **pAHexpt, + BitIOInfo* pIO, const Int iQP, Int *pCoef, CAdaptiveScan *pScan) +{ + const Int iContextOffset = CTDC + CONTEXTX; + UInt iLoc = 1; + Int iSR, iSRn, iIndex, iNumNonzero = 1, iCont, iSign, iLevel; + struct CAdaptiveHuffman **pAH1 = pAHexpt + iContextOffset + bChroma * 3; + const CAdaptiveScan *pConstScan = (const CAdaptiveScan *) pScan; + + /** first symbol **/ + DecodeFirstIndex (&iIndex, /*&iSign, */pAH1[0], pIO); + iSR = (iIndex & 1); + iSRn = iIndex >> 2; + + iCont = iSR & iSRn; + iSign = _getSign(pIO); + + iLevel = (iQP ^ iSign) - iSign; + if (iIndex & 2 /* iSL */) { + iLevel *= DecodeSignificantAbsLevel (pAHexpt[6 + iContextOffset + iCont], pIO);// ^ iSign) - iSign; + } + //else { + // iLevel = (1 | iSign); // 0 -> 1; -1 -> -1 + //} + if (iSR == 0) { + iLoc += DecodeSignificantRun (15 - iLoc, pAHexpt[0], pIO); + } + iLoc &= 0xf; + pCoef[pConstScan[iLoc].uScan] = (PixelI) iLevel;//(PixelI)(iQP * iLevel); + pScan[iLoc].uTotal++; + if (iLoc && pScan[iLoc].uTotal > pScan[iLoc - 1].uTotal) { + CAdaptiveScan cTemp = pScan[iLoc]; + pScan[iLoc] = pScan[iLoc - 1]; + pScan[iLoc - 1] = cTemp; + } + iLoc = (iLoc + 1) & 0xf; + //iLoc++; + + while (iSRn != 0) { + iSR = iSRn & 1; + if (iSR == 0) { + iLoc += DecodeSignificantRun (15 - iLoc, pAHexpt[0], pIO); + if (iLoc >= 16) + return 16; + } + DecodeIndex (&iIndex, /*&iSign, */iLoc + 1, pAH1[iCont + 1], pIO); + iSRn = iIndex >> 1; + + assert (iSRn >= 0 && iSRn < 3); + iCont &= iSRn; /** huge difference! **/ + iSign = _getSign(pIO); + + iLevel = (iQP ^ iSign) - iSign; + if (iIndex & 1 /* iSL */) { + iLevel *= DecodeSignificantAbsLevel (pAHexpt[6 + iContextOffset + iCont], pIO);// ^ iSign) - iSign; + //iLevel = (DecodeSignificantAbsLevel (pAHexpt[6 + iContextOffset + iCont], pIO) ^ iSign) - iSign; + } + //else { + // iLevel = (1 | iSign); // 0 -> 1; -1 -> -1 (was 1 + (iSign * 2)) + //} + + pCoef[pConstScan[iLoc].uScan] = (PixelI) iLevel;//(PixelI)(iQP * iLevel); + pScan[iLoc].uTotal++; + if (iLoc && pScan[iLoc].uTotal > pScan[iLoc - 1].uTotal) { + CAdaptiveScan cTemp = pScan[iLoc]; + pScan[iLoc] = pScan[iLoc - 1]; + pScan[iLoc - 1] = cTemp; + } + + iLoc = (iLoc + 1) & 0xf; + iNumNonzero++; + } + return iNumNonzero; +} + +/************************************************************************* + DecodeBlockAdaptive +*************************************************************************/ +static _FORCEINLINE Int DecodeBlockAdaptive (Bool bNoSkip, Bool bChroma, CAdaptiveHuffman **pAdHuff, + BitIOInfo *pIO, BitIOInfo *pIOFL, + PixelI *pCoeffs, CAdaptiveScan *pScan, + const Int iModelBits, const Int iTrim, const Int iQP, + const Int *pOrder, const Bool bSkipFlexbits) +{ + // const Int iLocation = 1; + // const Int iContextOffset = CTDC + CONTEXTX; + Int kk, iNumNonzero = 0, iFlex = iModelBits - iTrim; + + if (iFlex < 0 || bSkipFlexbits) + iFlex = 0; + + if (bNoSkip) { + const Int iQP1 = (iQP << iModelBits); + iNumNonzero = DecodeBlockHighpass (bChroma, pAdHuff, pIO, iQP1, pCoeffs, pScan); + } + if (iFlex) { + UInt k; + if (iQP + iTrim == 1) { // only iTrim = 0, iQP = 1 is legal + assert (iTrim == 0); + assert (iQP == 1); + + for (k = 1; k < 16; k++) { + PixelI *pk = pCoeffs + pOrder[k]; + if (*pk < 0) { + Int fine = _getBit16(pIOFL, iFlex); + *pk -= (PixelI)(fine); + } + else if (*pk > 0) { + Int fine = _getBit16(pIOFL, iFlex); + *pk += (PixelI)(fine); + } + else { + *pk = (PixelI)(_getBit16s(pIOFL, iFlex)); + } + } + } + else { + const Int iQP1 = iQP << iTrim; + for (k = 1; k < 16; k++) { + kk = pCoeffs[pOrder[k]]; + if (kk < 0) { + Int fine = _getBit16(pIOFL, iFlex); + pCoeffs[pOrder[k]] -= (PixelI)(iQP1 * fine); + } + else if (kk > 0) { + Int fine = _getBit16(pIOFL, iFlex); + pCoeffs[pOrder[k]] += (PixelI)(iQP1 * fine); + } + else { + pCoeffs[pOrder[k]] = (PixelI)(iQP1 * _getBit16s(pIOFL, iFlex)); + } + } + } + } + + return iNumNonzero; +} + + +/************************************************************************* + GetCoeffs +*************************************************************************/ +static _FORCEINLINE Int DecodeCoeffs (CWMImageStrCodec * pSC, CCodingContext *pContext, + Int iMBX, Int iMBY, + BitIOInfo* pIO, BitIOInfo *pIOFL) +{ + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (Int) pSC->m_param.cNumChannels; + const Int iPlanes = (cf == YUV_420 || cf == YUV_422) ? 1 : iChannels; + Int iQP; + CAdaptiveScan *pScan; + PixelI *pCoeffs; + Int i, iBlock, iSubblock, iNBlocks = 4; + Int iModelBits = pContext->m_aModelAC.m_iFlcBits[0]; + Int aLaplacianMean[2] = { 0, 0}, *pLM = aLaplacianMean + 0; + const Int *pOrder = dctIndex[0]; + const Int iOrient = pSC->MBInfo.iOrientation; + Bool bChroma = FALSE; + + Int iCBPCU = pSC->MBInfo.iCBP[1]; + Int iCBPCV = pSC->MBInfo.iCBP[2]; + Int iCBPCY = pSC->MBInfo.iCBP[0]; + + UNREFERENCED_PARAMETER( iMBX ); + UNREFERENCED_PARAMETER( iMBY ); + + /** set scan arrays and other MB level constants **/ + if (iOrient == 1) { + pScan = pContext->m_aScanVert; + } + else { + pScan = pContext->m_aScanHoriz; + } + + if (cf == YUV_420) { + iNBlocks = 6; + iCBPCY += (iCBPCU << 16) + (iCBPCV << 20); + } + else if (cf == YUV_422) { + iNBlocks = 8; + iCBPCY += (iCBPCU << 16) + (iCBPCV << 24); + } + + for (i = 0; i < iPlanes; i++) { + Int iIndex = 0, iNumNonZero; + + if(pSC->WMISCP.sbSubband != SB_NO_FLEXBITS) + readIS_L1(pSC, pIOFL); + + for (iBlock = 0; iBlock < iNBlocks; iBlock++) { + + readIS_L2(pSC, pIO); + if (pIO != pIOFL) + readIS_L2(pSC, pIOFL); + + iQP = (pSC->m_param.bTranscode ? 1 : pTile->pQuantizerHP[iPlanes > 1 ? i : (iBlock > 3 ? (cf == YUV_420 ? iBlock - 3 : iBlock / 2 - 1) : 0)][pSC->MBInfo.iQIndexHP].iQP); + + for (iSubblock = 0; iSubblock < 4; iSubblock++, iIndex++, iCBPCY >>= 1) { + pCoeffs = pSC->p1MBbuffer[i] + blkOffset[iIndex & 0xf]; + + //if (iBlock < 4) {//(cf == YUV_444) { + //bBlockNoSkip = ((iTempCBPC & (1 << iIndex1)) != 0); + //pCoeffs = pSC->p1MBbuffer[iBlock >> 2] + blkOffset[iIndex & 0xf]; + //} + //else { + if (iBlock >= 4) { + if(cf == YUV_420) { + pCoeffs = pSC->p1MBbuffer[iBlock - 3] + blkOffsetUV[iSubblock]; + } + else { // YUV_422 + pCoeffs = pSC->p1MBbuffer[1 + (1 & (iBlock >> 1))] + ((iBlock & 1) * 32) + blkOffsetUV_422[iSubblock]; + } + } + + /** read AC values **/ + assert (pSC->m_Dparam->bSkipFlexbits == 0 || pSC->WMISCP.bfBitstreamFormat == FREQUENCY || pSC->WMISCP.sbSubband == SB_NO_FLEXBITS); + iNumNonZero = DecodeBlockAdaptive ((iCBPCY & 1), bChroma, pContext->m_pAHexpt, + pIO, pIOFL, pCoeffs, pScan, iModelBits, pContext->m_iTrimFlexBits, + iQP, pOrder, pSC->m_Dparam->bSkipFlexbits); + if(iNumNonZero > 16) // something is wrong! + return ICERR_ERROR; + // shouldn't this be > 15? + (*pLM) += iNumNonZero; + } + if (iBlock == 3) { + iModelBits = pContext->m_aModelAC.m_iFlcBits[1]; + pLM = aLaplacianMean + 1; + bChroma = TRUE; + } + } + + iCBPCY = pSC->MBInfo.iCBP[(i + 1) & 0xf]; + assert (MAX_CHANNELS == 16); + } + + /** update model at end of MB **/ + UpdateModelMB (cf, iChannels, aLaplacianMean, &(pContext->m_aModelAC)); + return ICERR_OK; +} + +/************************************************************************* + DecodeSignificantAbsLevel +*************************************************************************/ +#ifndef X86OPT_INLINE +static Int DecodeSignificantAbsLevel (struct CAdaptiveHuffman *pAHexpt, BitIOInfo* pIO) +#else +static __forceinline Int DecodeSignificantAbsLevel (struct CAdaptiveHuffman *pAHexpt, BitIOInfo* pIO) +#endif +{ + UInt iIndex; + Int iFixed, iLevel; + static const Int aRemap[] = { 2, 3, 4, 6, 10, 14 }; + static const Int aFixedLength[] = { 0, 0, 1, 2, 2, 2 }; + + iIndex = (UInt)getHuff (pAHexpt->m_hufDecTable, pIO); + assert(iIndex <= 6); + pAHexpt->m_iDiscriminant += pAHexpt->m_pDelta[iIndex]; + if (iIndex < 2) { + iLevel = iIndex + 2; // = aRemap[iIndex] + } + else if (iIndex < 6) { + iFixed = aFixedLength[iIndex]; + iLevel = aRemap[iIndex] + _getBit16 (pIO, iFixed); + } + else{ + iFixed = _getBit16 (pIO, 4) + 4; + if (iFixed == 19) { + iFixed += _getBit16 (pIO, 2); + if (iFixed == 22) { + iFixed += _getBit16 (pIO, 3); + } + } + iLevel = 2 + (1 << iFixed); + iIndex = getBit32 (pIO, iFixed); + iLevel += iIndex; + } + return iLevel; +} + +U8 decodeQPIndex(BitIOInfo* pIO,U8 cBits) +{ + if(_getBit16(pIO, 1) == 0) + return 0; + return (U8)(_getBit16(pIO, cBits) + 1); +} + +/************************************************************************* + DecodeSecondStageCoeff +*************************************************************************/ +Int DecodeMacroblockLowpass (CWMImageStrCodec * pSC, CCodingContext *pContext, + Int iMBX, Int iMBYdummy) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (Int) pSC->m_param.cNumChannels; + const Int iFullPlanes = (cf == YUV_420 || cf == YUV_422) ? 2 : iChannels; + Int k; + CAdaptiveScan *pScan = pContext->m_aScanLowpass; + BitIOInfo* pIO = pContext->m_pIOLP; + Int iModelBits = pContext->m_aModelLP.m_iFlcBits[0]; + Int aRLCoeffs[32], iNumNonzero = 0, iIndex = 0; + Int aLaplacianMean[2] = { 0, 0}, *pLM = aLaplacianMean; + Int iChannel, iCBP = 0; +#ifndef ARMOPT_BITIO // ARM opt always uses 32-bit version of getBits + U32 (*getBits)(BitIOInfo* pIO, U32 cBits) = _getBit16; +#endif + CWMIMBInfo * pMBInfo = &pSC->MBInfo; + I32 *aDC[MAX_CHANNELS]; + + UNREFERENCED_PARAMETER( iMBX ); + UNREFERENCED_PARAMETER( iMBYdummy ); + + readIS_L1(pSC, pIO); + if((pSC->WMISCP.bfBitstreamFormat != SPATIAL) && (pSC->pTile[pSC->cTileColumn].cBitsLP > 0)) // MB-based LP QP index + pMBInfo->iQIndexLP = decodeQPIndex(pIO, pSC->pTile[pSC->cTileColumn].cBitsLP); + + // set arrays + for (k = 0; k < (Int) pSC->m_param.cNumChannels; k++) { + aDC[k & 15] = pMBInfo->iBlockDC[k]; + } + + /** reset adaptive scan totals **/ + if (pSC->m_bResetRGITotals) { + int iScale = 2; + int iWeight = iScale * 16; + pScan[0].uTotal = MAXTOTAL; + for (k = 1; k < 16; k++) { + pScan[k].uTotal = iWeight; + iWeight -= iScale; + } + } + + /** in raw mode, this can take 6% of the bits in the extreme low rate case!!! **/ + if (cf == YUV_420 || cf == YUV_422 || cf == YUV_444) { + int iCountM = pContext->m_iCBPCountMax, iCountZ = pContext->m_iCBPCountZero; + int iMax = iFullPlanes * 4 - 5; /* actually (1 << iNChannels) - 1 **/ + if (iCountZ <= 0 || iCountM < 0) { + iCBP = 0; + if (_getBool16 (pIO)) { + iCBP = 1; + k = _getBit16 (pIO, iFullPlanes - 1); + if (k) { + iCBP = k * 2 + _getBit16(pIO, 1); + } + } + if (iCountM < iCountZ) + iCBP = iMax - iCBP; + } + else { + iCBP = _getBit16(pIO, iFullPlanes); + } + + iCountM += 1 - 4 * (iCBP == iMax);//(b + c - 2*a); + iCountZ += 1 - 4 * (iCBP == 0);//(a + b - 2*c); + if (iCountM < -8) + iCountM = -8; + else if (iCountM > 7) + iCountM = 7; + pContext->m_iCBPCountMax = iCountM; + + if (iCountZ < -8) + iCountZ = -8; + else if (iCountZ > 7) + iCountZ = 7; + pContext->m_iCBPCountZero = iCountZ; + } + else { /** 1 or N channel **/ + for (iChannel = 0; iChannel < iChannels; iChannel++) + iCBP |= (getBits (pIO, 1) << iChannel); + } + +#ifndef ARMOPT_BITIO // ARM opt always uses 32-bit version of getBits + if (pContext->m_aModelLP.m_iFlcBits[0] > 14 || pContext->m_aModelLP.m_iFlcBits[1] > 14) { + getBits = getBit32; + } +#endif + + for (iChannel = 0; iChannel < iFullPlanes; iChannel++) { + PixelI *pCoeffs = aDC[iChannel]; + + if (iCBP & 1) { + iNumNonzero = DecodeBlock (iChannel > 0, aRLCoeffs, pContext->m_pAHexpt, + CTDC, pIO, 1 + 9 * ((cf == YUV_420) && (iChannel == 1)) + + ((cf == YUV_422) && (iChannel == 1))); + + if ((cf == YUV_420 || cf == YUV_422) && iChannel) { + Int aTemp[16]; //14 required, 16 for security + static const Int aRemap[] = { 4, 1,2,3, 5,6,7 }; + const Int *pRemap = aRemap + (cf == YUV_420); + const Int iCount = (cf == YUV_420) ? 6 : 14; + + (*pLM) += iNumNonzero; + iIndex = 0; + memset (aTemp, 0, sizeof(aTemp)); + + for (k = 0; k < iNumNonzero; k++) { + iIndex += aRLCoeffs[k * 2]; + aTemp[iIndex & 0xf] = aRLCoeffs[k * 2 + 1]; + iIndex++; + } + + for (k = 0; k < iCount; k++) { + aDC[(k & 1) + 1][pRemap[k >> 1]] = aTemp[k]; + } + } + else { + (*pLM) += iNumNonzero; + iIndex = 1; + + for (k = 0; k < iNumNonzero; k++) { + iIndex += aRLCoeffs[k * 2]; + pCoeffs[pScan[iIndex].uScan] = aRLCoeffs[k * 2 + 1]; + pScan[iIndex].uTotal++; + if (pScan[iIndex].uTotal > pScan[iIndex - 1].uTotal) { + CAdaptiveScan cTemp = pScan[iIndex]; + pScan[iIndex] = pScan[iIndex - 1]; + pScan[iIndex - 1] = cTemp; + } + iIndex++; + } + } + } + + if (iModelBits) { + if ((cf == YUV_420 || cf == YUV_422) && iChannel) { + for (k = 1; k < (cf == YUV_420 ? 4 : 8); k++) { + if (aDC[1][k] > 0) { + aDC[1][k] <<= iModelBits; + aDC[1][k] += getBits (pIO, iModelBits); + } + else if (aDC[1][k] < 0) { + aDC[1][k] <<= iModelBits; + aDC[1][k] -= getBits (pIO, iModelBits); + } + else { + aDC[1][k] = getBits (pIO, iModelBits); + if (aDC[1][k] && _getBool16 (pIO)) + aDC[1][k] = -aDC[1][k]; + } + + if (aDC[2][k] > 0) { + aDC[2][k] <<= iModelBits; + aDC[2][k] += getBits (pIO, iModelBits); + } + else if (aDC[2][k] < 0) { + aDC[2][k] <<= iModelBits; + aDC[2][k] -= getBits (pIO, iModelBits); + } + else { + aDC[2][k] = getBits (pIO, iModelBits); + if (aDC[2][k] && _getBool16 (pIO)) + aDC[2][k] = -aDC[2][k]; + } + } + } + else { +#ifdef _WIN32 + const Int iMask = (1 << iModelBits) - 1; +#endif // _WIN32 + for (k = 1; k < 16; k++) { +#ifdef _WIN32 + if (pCoeffs[k]) { + Int r1 = _rotl(pCoeffs[k], iModelBits); + pCoeffs[k] = (r1 ^ getBits(pIO, iModelBits)) - (r1 & iMask); + } +#else // _WIN32 + if (pCoeffs[k] > 0) { + pCoeffs[k] <<= iModelBits; + pCoeffs[k] += getBits (pIO, iModelBits); + } + else if (pCoeffs[k] < 0) { + pCoeffs[k] <<= iModelBits; + pCoeffs[k] -= getBits (pIO, iModelBits); + } +#endif // _WIN32 + else { + //pCoeffs[k] = getBits (pIO, iModelBits); + //if (pCoeffs[k] && _getBool16 (pIO)) + // pCoeffs[k] = -pCoeffs[k]; + Int r1 = _peekBit16 (pIO, iModelBits + 1); + pCoeffs[k] = ((r1 >> 1) ^ (-(r1 & 1))) + (r1 & 1); + _flushBit16 (pIO, iModelBits + (pCoeffs[k] != 0)); + } + } + } + } + pLM = aLaplacianMean + 1; + iModelBits = pContext->m_aModelLP.m_iFlcBits[1]; + + iCBP >>= 1; + } + + UpdateModelMB (cf, iChannels, aLaplacianMean, &(pContext->m_aModelLP)); + + if (pSC->m_bResetContext) { + AdaptLowpassDec(pContext); + } + + return ICERR_OK; +} + +/************************************************************************* + 8 bit YUV 420 macroblock decode function with 4x4 transform + Index order is as follows: + Y: U: V: + 0 1 4 5 16 17 20 21 + 2 3 6 7 18 19 22 23 + 8 9 12 13 + 10 11 14 15 + + DCAC coefficients stored for 4x4 - offsets (x == no storage) + Y: + x x x [0..3] + x x x [4..7] + x x x [8..11] + [16..19] [20..23] [24..27] [28..31,12..15] + + U, V: + x [0..3] + [8..11] [4..7,12..15] +*************************************************************************/ +Int DecodeMacroblockDC(CWMImageStrCodec * pSC, CCodingContext *pContext, Int iMBX, Int iMBY) +{ + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + CWMIMBInfo * pMBInfo = &pSC->MBInfo; + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (Int) pSC->m_param.cNumChannels; + BitIOInfo* pIO = pContext->m_pIODC; + Int iIndex, i; + Int aLaplacianMean[2] = { 0, 0}, *pLM = aLaplacianMean; + Int iModelBits = pContext->m_aModelDC.m_iFlcBits[0]; + struct CAdaptiveHuffman *pAH; + Int iQDCY, iQDCU, iQDCV; + // const Int iChromaElements = (cf == YUV_420) ? 8 * 8 : ((cf == YUV_422) ? 8 * 16 : 16 * 16); + + UNREFERENCED_PARAMETER( iMBX ); + UNREFERENCED_PARAMETER( iMBY ); + + for (i = 0; i < iChannels; i++) + memset (pMBInfo->iBlockDC[i], 0, 16 * sizeof (I32)); + + readIS_L1(pSC, pIO); + + pMBInfo->iQIndexLP = pMBInfo->iQIndexHP = 0; + + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL && pSC->WMISCP.sbSubband != SB_DC_ONLY){ + if(pTile->cBitsLP > 0) // MB-based LP QP index + pMBInfo->iQIndexLP = decodeQPIndex(pIO, pTile->cBitsLP); + if( pSC->WMISCP.sbSubband != SB_NO_HIGHPASS && pTile->cBitsHP > 0) // MB-based HP QP index + pMBInfo->iQIndexHP = decodeQPIndex(pIO, pTile->cBitsHP); + } + if(pTile->cBitsHP == 0 && pTile->cNumQPHP > 1) // use LP QP + pMBInfo->iQIndexHP = pMBInfo->iQIndexLP; + if (pMBInfo->iQIndexLP >= pTile->cNumQPLP || pMBInfo->iQIndexHP >= pTile->cNumQPHP) + return ICERR_ERROR; + + if(cf == Y_ONLY || cf == CMYK || cf == NCOMPONENT) { + for (i = 0; i < iChannels; i++) { + iQDCY = 0; + /** get luminance DC **/ + if (_getBool16 (pIO)) { + iQDCY = DecodeSignificantAbsLevel(pContext->m_pAHexpt[3], pIO) - 1; + *pLM += 1; + } + if (iModelBits) { + iQDCY = (iQDCY << iModelBits) | _getBit16(pIO, iModelBits); + } + if (iQDCY && _getBool16 (pIO)) + iQDCY = -iQDCY; + pMBInfo->iBlockDC[i][0] = iQDCY; + + pLM = aLaplacianMean + 1; + iModelBits = pContext->m_aModelDC.m_iFlcBits[1]; + } + } + else { + /** find significant level in 3D **/ + pAH = pContext->m_pAHexpt[2]; + iIndex = getHuff (pAH->m_hufDecTable, pIO); + iQDCY = iIndex >> 2; + iQDCU = (iIndex >> 1) & 1; + iQDCV = iIndex & 1; + + /** get luminance DC **/ + if (iQDCY) { + iQDCY = DecodeSignificantAbsLevel(pContext->m_pAHexpt[3], pIO) - 1; + *pLM += 1; + } + if (iModelBits) { + iQDCY = (iQDCY << iModelBits) | _getBit16(pIO, iModelBits); + } + if (iQDCY && _getBool16 (pIO)) + iQDCY = -iQDCY; + pMBInfo->iBlockDC[0][0] = iQDCY; + + /** get chrominance DC **/ + pLM = aLaplacianMean + 1; + iModelBits = pContext->m_aModelDC.m_iFlcBits[1]; + + if (iQDCU) { + iQDCU = DecodeSignificantAbsLevel(pContext->m_pAHexpt[4], pIO) - 1; + *pLM += 1; + } + if (iModelBits) { + iQDCU = (iQDCU << iModelBits) | _getBit16(pIO, iModelBits); + } + if (iQDCU && _getBool16 (pIO)) + iQDCU = -iQDCU; + pMBInfo->iBlockDC[1][0] = iQDCU; + + if (iQDCV) { + iQDCV = DecodeSignificantAbsLevel(pContext->m_pAHexpt[4], pIO) - 1; + *pLM += 1; + } + if (iModelBits) { + iQDCV = (iQDCV << iModelBits) | _getBit16(pIO, iModelBits); + } + if (iQDCV && _getBool16 (pIO)) + iQDCV = -iQDCV; + pMBInfo->iBlockDC[2][0] = iQDCV; + } + + UpdateModelMB (cf, iChannels, aLaplacianMean, &(pContext->m_aModelDC)); + + if(((!(pSC->WMISCP.bfBitstreamFormat != FREQUENCY || pSC->m_Dparam->cThumbnailScale < 16)) || pSC->WMISCP.sbSubband == SB_DC_ONLY) && pSC->m_bResetContext){ + Int kk; + for (kk = 2; kk < 5; kk++) { + if (ICERR_OK != AdaptDecFixed (pContext->m_pAHexpt[kk])) { + return ICERR_ERROR; + } + } + } + + return ICERR_OK; +} + +/************************************************************************* + DecodeMacroblockHighpass +*************************************************************************/ +Int DecodeMacroblockHighpass (CWMImageStrCodec *pSC, CCodingContext *pContext, + Int iMBX, Int iMBY) +{ + /** reset adaptive scan totals **/ + if (pSC->m_bResetRGITotals) { + int iScale = 2, k; + int iWeight = iScale * 16; + pContext->m_aScanHoriz[0].uTotal = pContext->m_aScanVert[0].uTotal = MAXTOTAL; + for (k = 1; k < 16; k++) { + pContext->m_aScanHoriz[k].uTotal = pContext->m_aScanVert[k].uTotal = iWeight; + iWeight -= iScale; + } + } + if((pSC->WMISCP.bfBitstreamFormat != SPATIAL) && (pSC->pTile[pSC->cTileColumn].cBitsHP > 0)) { // MB-based HP QP index + pSC->MBInfo.iQIndexHP = decodeQPIndex(pContext->m_pIOAC, pSC->pTile[pSC->cTileColumn].cBitsHP); + if (pSC->MBInfo.iQIndexHP >= pSC->pTile[pSC->cTileColumn].cNumQPHP) + goto ErrorExit; + } + else if(pSC->pTile[pSC->cTileColumn].cBitsHP == 0 && pSC->pTile[pSC->cTileColumn].cNumQPHP > 1) // use LP QP + pSC->MBInfo.iQIndexHP = pSC->MBInfo.iQIndexLP; + + + DecodeCBP (pSC, pContext); + predCBPDec(pSC, pContext); + + if (DecodeCoeffs (pSC, pContext, iMBX, iMBY, + pContext->m_pIOAC, pContext->m_pIOFL) != ICERR_OK) + goto ErrorExit; + + if (pSC->m_bResetContext) { + AdaptHighpassDec(pContext); + } + + return ICERR_OK; +ErrorExit: + return ICERR_ERROR; +} + +/************************************************************************* + Adapt +*************************************************************************/ +Int AdaptLowpassDec(CCodingContext * pSC) +{ + Int kk; + for (kk = 0; kk < CONTEXTX + CTDC; kk++) { + if (ICERR_OK != AdaptDecFixed (pSC->m_pAHexpt[kk])) { + goto ErrorExit; + } + } + return ICERR_OK; + +ErrorExit: + return ICERR_ERROR; + +} + +Int AdaptHighpassDec(CCodingContext * pSC) +{ + Int kk; + if (ICERR_OK != AdaptDecFixed (pSC->m_pAdaptHuffCBPCY)) { + goto ErrorExit; + } + if (ICERR_OK != AdaptDecFixed (pSC->m_pAdaptHuffCBPCY1)) { + goto ErrorExit; + } + for (kk = 0; kk < CONTEXTX; kk++) { + if (ICERR_OK != AdaptDecFixed (pSC->m_pAHexpt[kk + CONTEXTX + CTDC])) { + goto ErrorExit; + } + } + + return ICERR_OK; + +ErrorExit: + return ICERR_ERROR; +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/segdec.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/segdec.o new file mode 100644 index 0000000..52415a7 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/segdec.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strInvTransform.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strInvTransform.c new file mode 100644 index 0000000..123ede6 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strInvTransform.c @@ -0,0 +1,1888 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strTransform.h" +#include "strcodec.h" +#include "decode.h" + +/** rotation by -pi/8 **/ +#define IROTATE1(a, b) (a) -= (((b) + 1) >> 1), (b) += (((a) + 1) >> 1) // this works well too +#define IROTATE2(a, b) (a) -= (((b)*3 + 4) >> 3), (b) += (((a)*3 + 4) >> 3) // this works well too + +/** local functions **/ +static Void invOddOdd(PixelI *, PixelI *, PixelI *, PixelI *); +static Void invOddOddPost(PixelI *, PixelI *, PixelI *, PixelI *); +static Void invOdd(PixelI *, PixelI *, PixelI *, PixelI *); +static Void strHSTdec(PixelI *, PixelI *, PixelI *, PixelI *); +static Void strHSTdec1(PixelI *, PixelI *); +static Void strHSTdec1_alternate(PixelI *, PixelI *); +static Void strHSTdec1_edge(PixelI *pa, PixelI *pd); + +/** IDCT stuff **/ +/** reordering should be combined with zigzag scan **/ +/** data order before IDCT **/ +/** 0 8 4 6 **/ +/** 2 10 14 12 **/ +/** 1 11 15 13 **/ +/** 9 3 7 5 **/ +/** data order after IDCT **/ +/** 0 1 2 3 **/ +/** 4 5 6 7 **/ +/** 8 9 10 11 **/ +/** 12 13 14 15 **/ +Void strIDCT4x4Stage1(PixelI* p) +{ + /** top left corner, butterfly => butterfly **/ + strDCT2x2up(p + 0, p + 1, p + 2, p + 3); + + /** top right corner, -pi/8 rotation => butterfly **/ + invOdd(p + 5, p + 4, p + 7, p + 6); + + /** bottom left corner, butterfly => -pi/8 rotation **/ + invOdd(p + 10, p + 8, p + 11, p + 9); + + /** bottom right corner, -pi/8 rotation => -pi/8 rotation **/ + invOddOdd(p + 15, p + 14, p + 13, p + 12); + + /** butterfly **/ + //FOURBUTTERFLY(p, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); + FOURBUTTERFLY_HARDCODED1(p); +} + +Void strIDCT4x4Stage2(PixelI* p) +{ + /** bottom left corner, butterfly => -pi/8 rotation **/ + invOdd(p + 32, p + 48, p + 96, p + 112); + + /** top right corner, -pi/8 rotation => butterfly **/ + invOdd(p + 128, p + 192, p + 144, p + 208); + + /** bottom right corner, -pi/8 rotation => -pi/8 rotation **/ + invOddOdd(p + 160, p + 224, p + 176, p + 240); + + /** top left corner, butterfly => butterfly **/ + strDCT2x2up(p + 0, p + 64, p + 16, p + 80); + + /** butterfly **/ + FOURBUTTERFLY(p, 0, 192, 48, 240, 64, 128, 112, 176, 16, 208, 32, 224, 80, 144, 96, 160); +} + +Void strNormalizeDec(PixelI* p, Bool bChroma) +{ + int i; + if (!bChroma) { + //for (i = 0; i < 256; i += 16) { + // p[i] <<= 2; + //} + } + else { + for (i = 0; i < 256; i += 16) { + p[i] += p[i]; + } + } +} + +/** 2x2 DCT with post-scaling - for use on decoder side **/ +Void strDCT2x2dnDec(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, C, t; + a = *pa; + b = *pb; + C = *pc; + d = *pd; + + a += d; + b -= C; + t = ((a - b) >> 1); + c = t - d; + d = t - C; + a -= d; + b += c; + + *pa = a * 2; + *pb = b * 2; + *pc = c * 2; + *pd = d * 2; +} + + +/** post filter stuff **/ +/** 2-point post for boundaries **/ +Void strPost2(PixelI * a, PixelI * b) +{ + *b += ((*a + 4) >> 3); + *a += ((*b + 2) >> 2); + *b += ((*a + 4) >> 3); +} + +Void strPost2_alternate(PixelI * pa, PixelI * pb) +{ + PixelI a, b; + a = *pa; + b = *pb; + + /** rotate **/ + b += ((a + 2) >> 2); + a += ((b + 1) >> 1); + a += (b >> 5); + a += (b >> 9); + a += (b >> 13); + + b += ((a + 2) >> 2); + + *pa = a; + *pb = b; +} + +Void strPost2x2(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + a += d; + b += c; + d -= (a + 1) >> 1; + c -= (b + 1) >> 1; + + /** rotate **/ + b += ((a + 2) >> 2); + a += ((b + 1) >> 1); + b += ((a + 2) >> 2); + + /** butterflies **/ + d += (a + 1) >> 1; + c += (b + 1) >> 1; + a -= d; + b -= c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +Void strPost2x2_alternate(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + a += d; + b += c; + d -= (a + 1) >> 1; + c -= (b + 1) >> 1; + + /** rotate **/ + b += ((a + 2) >> 2); + a += ((b + 1) >> 1); + a += (b >> 5); + a += (b >> 9); + a += (b >> 13); + b += ((a + 2) >> 2); + + /** butterflies **/ + d += (a + 1) >> 1; + c += (b + 1) >> 1; + a -= d; + b -= c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +/** 4-point post for boundaries **/ +Void strPost4(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + a += d, b += c; + d -= ((a + 1) >> 1), c -= ((b + 1) >> 1); + + IROTATE1(c, d); + + d += ((a + 1) >> 1), c += ((b + 1) >> 1); + a -= d - ((d * 3 + 16) >> 5), b -= c - ((c * 3 + 16) >> 5); + d += ((a * 3 + 8) >> 4), c += ((b * 3 + 8) >> 4); + a += ((d * 3 + 16) >> 5), b += ((c * 3 + 16) >> 5); + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +Void strPost4_alternate(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + a += d, b += c; + d -= ((a + 1) >> 1), c -= ((b + 1) >> 1); + + strHSTdec1_edge(&a, &d); strHSTdec1_edge(&b, &c); + IROTATE1(c, d); + d += ((a + 1) >> 1), c += ((b + 1) >> 1); + + a -= d, b -= c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +/***************************************************************************************** + Input data offsets: + (15)(14)|(10+64)(11+64) p0 (15)(14)|(74)(75) + (13)(12)|( 8+64)( 9+64) (13)(12)|(72)(73) + --------+-------------- --------+-------- + ( 5)( 4)|( 0+64) (1+64) p1 ( 5)( 4)|(64)(65) + ( 7)( 6)|( 2+64) (3+64) ( 7)( 6)|(66)(67) +*****************************************************************************************/ +Void DCCompensate (PixelI *a, PixelI *b, PixelI *c, PixelI *d, int iDC) +{ + iDC = iDC>>1; + *a -= iDC; + *d -= iDC; + *b += iDC; + *c += iDC; +} + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +int ClipDCL(int iDCL, int iAltDCL) +{ + int iClipDCL = 0; + if (iDCL > 0) { + if (iAltDCL > 0) + iClipDCL = min(iDCL, iAltDCL); + else + iClipDCL = 0; + } + else if (iDCL < 0) { + if (iAltDCL < 0) + iClipDCL = max(iDCL, iAltDCL); + else + iClipDCL = 0; + } + return iClipDCL; +} + +Void strPost4x4Stage1Split(PixelI *p0, PixelI *p1, Int iOffset, Int iHPQP, Bool bHPAbsent) +{ + int iDCLAlt1, iDCLAlt2, iDCLAlt3, iDCLAlt0; + int iDCL1, iDCL2, iDCL3, iDCL0; + int iTmp1, iTmp2, iTmp3, iTmp0; + + PixelI *p2 = p0 + 72 - iOffset; + PixelI *p3 = p1 + 64 - iOffset; + p0 += 12; + p1 += 4; + + /** buttefly **/ + strDCT2x2dn(p0 + 0, p2 + 0, p1 + 0, p3 + 0); + strDCT2x2dn(p0 + 1, p2 + 1, p1 + 1, p3 + 1); + strDCT2x2dn(p0 + 2, p2 + 2, p1 + 2, p3 + 2); + strDCT2x2dn(p0 + 3, p2 + 3, p1 + 3, p3 + 3); + + /** bottom right corner: -pi/8 rotation => -pi/8 rotation **/ + invOddOddPost(p3 + 0, p3 + 1, p3 + 2, p3 + 3); + + /** anti diagonal corners: rotation by -pi/8 **/ + IROTATE1(p1[2], p1[3]); + IROTATE1(p1[0], p1[1]); + IROTATE1(p2[1], p2[3]); + IROTATE1(p2[0], p2[2]); + + /** butterfly **/ + strHSTdec1(p0 + 0, p3 + 0); + strHSTdec1(p0 + 1, p3 + 1); + strHSTdec1(p0 + 2, p3 + 2); + strHSTdec1(p0 + 3, p3 + 3); + strHSTdec(p0 + 0, p2 + 0, p1 + 0, p3 + 0); + strHSTdec(p0 + 1, p2 + 1, p1 + 1, p3 + 1); + strHSTdec(p0 + 2, p2 + 2, p1 + 2, p3 + 2); + strHSTdec(p0 + 3, p2 + 3, p1 + 3, p3 + 3); + + iTmp0 = (*(p0 +0) + *(p1 +0) + *(p2 +0) + *(p3 +0))>>1; + iTmp1 = (*(p0 +1) + *(p1 +1) + *(p2 +1) + *(p3 +1))>>1; + iTmp2 = (*(p0 +2) + *(p1 +2) + *(p2 +2) + *(p3 +2))>>1; + iTmp3 = (*(p0 +3) + *(p1 +3) + *(p2 +3) + *(p3 +3))>>1; + iDCL0 = (iTmp0 * 595 + 65536)>>17; //Approximating 27/5947 + iDCL1 = (iTmp1 * 595 + 65536)>>17; + iDCL2 = (iTmp2 * 595 + 65536)>>17; + iDCL3 = (iTmp3 * 595 + 65536)>>17; + if ((abs(iDCL0) < iHPQP && iHPQP > 20) || bHPAbsent) { + iDCLAlt0 = (*(p0 +0) - *(p1 +0) - *(p2 +0) + *(p3 +0))>>1; + iDCL0 = ClipDCL (iDCL0, iDCLAlt0); + DCCompensate (p0 + 0, p2 + 0, p1 + 0, p3 + 0, iDCL0); + } + if ((abs(iDCL1) < iHPQP && iHPQP > 20) || bHPAbsent) { + iDCLAlt1 = (*(p0 +1) - *(p1 +1) - *(p2 +1) + *(p3 +1))>>1; + iDCL1 = ClipDCL (iDCL1, iDCLAlt1); + DCCompensate (p0 + 1, p2 + 1, p1 + 1, p3 + 1, iDCL1); + } + if ((abs(iDCL2) < iHPQP && iHPQP > 20) || bHPAbsent) { + iDCLAlt2 = (*(p0 +2) - *(p1 +2) - *(p2 +2) + *(p3 +2))>>1; + iDCL2 = ClipDCL (iDCL2, iDCLAlt2); + DCCompensate (p0 + 2, p2 + 2, p1 + 2, p3 + 2, iDCL2); + } + if ((abs(iDCL3) < iHPQP && iHPQP > 20) || bHPAbsent) { + iDCLAlt3 = (*(p0 +3) - *(p1 +3) - *(p2 +3) + *(p3 +3))>>1; + iDCL3 = ClipDCL (iDCL3, iDCLAlt3); + DCCompensate (p0 + 3, p2 + 3, p1 + 3, p3 + 3, iDCL3); + } +} + +Void strPost4x4Stage1(PixelI* p, Int iOffset, Int iHPQP, Bool bHPAbsent) +{ + strPost4x4Stage1Split(p, p + 16, iOffset, iHPQP, bHPAbsent); +} + +Void strPost4x4Stage1Split_alternate(PixelI *p0, PixelI *p1, Int iOffset) +{ + PixelI *p2 = p0 + 72 - iOffset; + PixelI *p3 = p1 + 64 - iOffset; + p0 += 12; + p1 += 4; + + /** buttefly **/ + strDCT2x2dn(p0 + 0, p2 + 0, p1 + 0, p3 + 0); + strDCT2x2dn(p0 + 1, p2 + 1, p1 + 1, p3 + 1); + strDCT2x2dn(p0 + 2, p2 + 2, p1 + 2, p3 + 2); + strDCT2x2dn(p0 + 3, p2 + 3, p1 + 3, p3 + 3); + + /** bottom right corner: -pi/8 rotation => -pi/8 rotation **/ + invOddOddPost(p3 + 0, p3 + 1, p3 + 2, p3 + 3); + + /** anti diagonal corners: rotation by -pi/8 **/ + IROTATE1(p1[2], p1[3]); + IROTATE1(p1[0], p1[1]); + IROTATE1(p2[1], p2[3]); + IROTATE1(p2[0], p2[2]); + + /** butterfly **/ + strHSTdec1_alternate(p0 + 0, p3 + 0); + strHSTdec1_alternate(p0 + 1, p3 + 1); + strHSTdec1_alternate(p0 + 2, p3 + 2); + strHSTdec1_alternate(p0 + 3, p3 + 3); + strHSTdec(p0 + 0, p2 + 0, p1 + 0, p3 + 0); + strHSTdec(p0 + 1, p2 + 1, p1 + 1, p3 + 1); + strHSTdec(p0 + 2, p2 + 2, p1 + 2, p3 + 2); + strHSTdec(p0 + 3, p2 + 3, p1 + 3, p3 + 3); +} + +Void strPost4x4Stage1_alternate(PixelI* p, Int iOffset) +{ + strPost4x4Stage1Split_alternate(p, p + 16, iOffset); +} + +/***************************************************************************************** + Input data offsets: + (15)(14)|(10+32)(11+32) p0 (15)(14)|(42)(43) + (13)(12)|( 8+32)( 9+32) (13)(12)|(40)(41) + --------+-------------- --------+-------- + ( 5)( 4)|( 0+32) (1+32) p1 ( 5)( 4)|(32)(33) + ( 7)( 6)|( 2+32) (3+32) ( 7)( 6)|(34)(35) +*****************************************************************************************/ + +/***************************************************************************************** + Input data offsets: + ( -96)(-32)|(32)( 96) p0 + ( -80)(-16)|(48)(112) + -----------+------------ + (-128)(-64)|( 0)( 64) p1 + (-112)(-48)|(16)( 80) +*****************************************************************************************/ +Void strPost4x4Stage2Split(PixelI* p0, PixelI* p1) +{ + /** buttefly **/ + strDCT2x2dn(p0 - 96, p0 + 96, p1 - 112, p1 + 80); + strDCT2x2dn(p0 - 32, p0 + 32, p1 - 48, p1 + 16); + strDCT2x2dn(p0 - 80, p0 + 112, p1 - 128, p1 + 64); + strDCT2x2dn(p0 - 16, p0 + 48, p1 - 64, p1 + 0); + + /** bottom right corner: -pi/8 rotation => -pi/8 rotation **/ + invOddOddPost(p1 + 0, p1 + 64, p1 + 16, p1 + 80); + + /** anti diagonal corners: rotation by -pi/8 **/ + IROTATE1(p0[ 48], p0[ 32]); + IROTATE1(p0[112], p0[ 96]); + IROTATE1(p1[-64], p1[-128]); + IROTATE1(p1[-48], p1[-112]); + + /** butterfly **/ + strHSTdec1(p0 - 96, p1 + 80); + strHSTdec1(p0 - 32, p1 + 16); + strHSTdec1(p0 - 80, p1 + 64); + strHSTdec1(p0 - 16, p1 + 0); + + strHSTdec(p0 - 96, p1 - 112, p0 + 96, p1 + 80); + strHSTdec(p0 - 32, p1 - 48, p0 + 32, p1 + 16); + strHSTdec(p0 - 80, p1 - 128, p0 + 112, p1 + 64); + strHSTdec(p0 - 16, p1 - 64, p0 + 48, p1 + 0); +} + +Void strPost4x4Stage2Split_alternate(PixelI* p0, PixelI* p1) +{ + /** buttefly **/ + strDCT2x2dn(p0 - 96, p0 + 96, p1 - 112, p1 + 80); + strDCT2x2dn(p0 - 32, p0 + 32, p1 - 48, p1 + 16); + strDCT2x2dn(p0 - 80, p0 + 112, p1 - 128, p1 + 64); + strDCT2x2dn(p0 - 16, p0 + 48, p1 - 64, p1 + 0); + + /** bottom right corner: -pi/8 rotation => -pi/8 rotation **/ + invOddOddPost(p1 + 0, p1 + 64, p1 + 16, p1 + 80); + + /** anti diagonal corners: rotation by -pi/8 **/ + IROTATE1(p0[ 48], p0[ 32]); + IROTATE1(p0[112], p0[ 96]); + IROTATE1(p1[-64], p1[-128]); + IROTATE1(p1[-48], p1[-112]); + + /** butterfly **/ + strHSTdec1_alternate(p0 - 96, p1 + 80); + strHSTdec1_alternate(p0 - 32, p1 + 16); + strHSTdec1_alternate(p0 - 80, p1 + 64); + strHSTdec1_alternate(p0 - 16, p1 + 0); + + strHSTdec(p0 - 96, p1 - 112, p0 + 96, p1 + 80); + strHSTdec(p0 - 32, p1 - 48, p0 + 32, p1 + 16); + strHSTdec(p0 - 80, p1 - 128, p0 + 112, p1 + 64); + strHSTdec(p0 - 16, p1 - 64, p0 + 48, p1 + 0); +} + +/** + Hadamard+Scale transform + for some strange reason, breaking up the function into two blocks, strHSTdec1 and strHSTdec + seems to work faster +**/ +static Void strHSTdec1(PixelI *pa, PixelI *pd) +{ + /** different realization : does rescaling as well! **/ + PixelI a, d; + a = *pa; + d = *pd; + + a += d; + d = (a >> 1) - d; + a += (d * 3 + 0) >> 3; + d += (a * 3 + 0) >> 4; + //a += (d * 3 + 4) >> 3; + + *pa = a; + *pd = d; +} + +static Void strHSTdec1_alternate(PixelI *pa, PixelI *pd) +{ + /** different realization : does rescaling as well! **/ + PixelI a, d; + a = *pa; + d = *pd; + + a += d; + d = (a >> 1) - d; + a += (d * 3 + 0) >> 3; + d += (a * 3 + 0) >> 4; + //a += (d * 3 + 4) >> 3; + + d += (a >> 7); + d -= (a >> 10); + + *pa = a; + *pd = d; +} + +static Void strHSTdec1_edge (PixelI *pa, PixelI *pd) +{ + /** different realization as compared to scaling operator for 2D case **/ + PixelI a, d; + a = *pa; + d = *pd; + + a += d; + d = (a >> 1) - d; + a += (d * 3 + 0) >> 3; + d += (a * 3 + 0) >> 4; + + //Scaling modification of adding 7/1024 in 2 steps (without multiplication by 7). + d += (a >> 7); + d -= (a >> 10); + + a += (d * 3 + 4) >> 3; + d -= (a >> 1); + a += d; + // End new operations + + *pa = a; + *pd = -d; // Negative sign needed here for 1D scaling case to ensure correct scaling. +} + +static Void strHSTdec(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + /** different realization : does rescaling as well! **/ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + b -= c; + a += (d * 3 + 4) >> 3; + + d -= (b >> 1); + c = ((a - b) >> 1) - c; + *pc = d; + *pd = c; + *pa = a - c, *pb = b + d; +} + +/** Kron(Rotate(pi/8), Rotate(pi/8)) **/ +static Void invOddOdd(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, t1, t2; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + d += a; + c -= b; + a -= (t1 = d >> 1); + b += (t2 = c >> 1); + + /** rotate pi/4 **/ + a -= (b * 3 + 3) >> 3; + b += (a * 3 + 3) >> 2; + a -= (b * 3 + 4) >> 3; + + /** butterflies **/ + b -= t2; + a += t1; + c += b; + d -= a; + + /** sign flips **/ + *pa = a; + *pb = -b; + *pc = -c; + *pd = d; +} + +/** Kron(Rotate(pi/8), Rotate(pi/8)) **/ +static Void invOddOddPost(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, t1, t2; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + d += a; + c -= b; + a -= (t1 = d >> 1); + b += (t2 = c >> 1); + + /** rotate pi/4 **/ + a -= (b * 3 + 6) >> 3; + b += (a * 3 + 2) >> 2; + a -= (b * 3 + 4) >> 3; + + /** butterflies **/ + b -= t2; + a += t1; + c += b; + d -= a; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + + +/** Kron(Rotate(-pi/8), [1 1; 1 -1]/sqrt(2)) **/ +/** [D C A B] => [a b c d] **/ +Void invOdd(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + b += d; + a -= c; + d -= (b) >> 1; + c += (a + 1) >> 1; + + /** rotate pi/8 **/ + IROTATE2(a, b); + IROTATE2(c, d); + + /** butterflies **/ + c -= (b + 1) >> 1; + d = ((a + 1) >> 1) - d; + b += c; + a -= d; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +/************************************************************************* + Top-level function to inverse tranform possible part of a macroblock +*************************************************************************/ +Int invTransformMacroblock(CWMImageStrCodec * pSC) +{ + const OVERLAP olOverlap = pSC->WMISCP.olOverlap; + const COLORFORMAT cfColorFormat = pSC->m_param.cfColorFormat; + // const BITDEPTH_BITS bdBitDepth = pSC->WMII.bdBitDepth; + const Bool left = (pSC->cColumn == 0), right = (pSC->cColumn == pSC->cmbWidth); + const Bool top = (pSC->cRow == 0), bottom = (pSC->cRow == pSC->cmbHeight); + const Bool topORbottom = (top || bottom), leftORright = (left || right); + const Bool topORleft = (top || left), bottomORright = (bottom || right); + const size_t mbWidth = pSC->cmbWidth, mbX = pSC->cColumn; + PixelI * p = NULL;// * pt = NULL; + size_t i; + const size_t iChannels = (cfColorFormat == YUV_420 || cfColorFormat == YUV_422) ? 1 : pSC->m_param.cNumChannels; + const size_t tScale = pSC->m_Dparam->cThumbnailScale; + Int j = 0; + + Int qp[MAX_CHANNELS], dcqp[MAX_CHANNELS], iStrength = (1 << pSC->WMII.cPostProcStrength); + // ERR_CODE result = ICERR_OK; + + Bool bHPAbsent = (pSC->WMISCP.sbSubband == SB_NO_HIGHPASS || pSC->WMISCP.sbSubband == SB_DC_ONLY); + + if(pSC->WMII.cPostProcStrength > 0){ + // threshold for post processing + for(i = 0; i < iChannels; i ++){ + qp[i] = pSC->pTile[pSC->cTileColumn].pQuantizerLP[i][pSC->MBInfo.iQIndexLP].iQP * iStrength * (olOverlap == OL_NONE ? 2 : 1); + dcqp[i] = pSC->pTile[pSC->cTileColumn].pQuantizerDC[i][0].iQP * iStrength; + } + + if(left) // a new MB row + slideOneMBRow(pSC->pPostProcInfo, pSC->m_param.cNumChannels, mbWidth, top, bottom); // previous current row becomes previous row + } + + //================================================================ + // 400_Y, 444_YUV + for (i = 0; i < iChannels && tScale < 16; ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[i]; + PixelI* const p1 = pSC->p1MBbuffer[i]; + + Int iHPQP = 255; + if (!bHPAbsent) + iHPQP = pSC->pTile[pSC->cTileColumn].pQuantizerHP[i][pSC->MBInfo.iQIndexHP].iQP; + + //================================ + // second level inverse transform + if (!bottomORright) + { + if(pSC->WMII.cPostProcStrength > 0) + updatePostProcInfo(pSC->pPostProcInfo, p1, mbX, i); // update postproc info before IDCT + + strIDCT4x4Stage2(p1); + if (pSC->m_param.bScaledArith) { + strNormalizeDec(p1, (i != 0)); + } + } + + //================================ + // second level inverse overlap + if (OL_TWO == olOverlap) + { + if (leftORright && (!topORbottom)) + { + j = left ? 0 : -128; + strPost4(p0 + j + 32, p0 + j + 48, p1 + j + 0, p1 + j + 16); + strPost4(p0 + j + 96, p0 + j + 112, p1 + j + 64, p1 + j + 80); + } + + if (!leftORright) + { + if (topORbottom) + { + p = top ? p1 : p0 + 32; + strPost4(p - 128, p - 64, p + 0, p + 64); + strPost4(p - 112, p - 48, p + 16, p + 80); + p = NULL; + } + else + { + strPost4x4Stage2Split(p0, p1); + } + } + } + + if(pSC->WMII.cPostProcStrength > 0) + postProcMB(pSC->pPostProcInfo, p0, p1, mbX, i, dcqp[i]); // second stage deblocking + + //================================ + // first level inverse transform + if(tScale >= 4) // bypass first level transform for 4:1 and smaller thumbnail + continue; + + if (!top) + { + for (j = (left ? 32 : -96); j < (right ? 32 : 160); j += 64) + { + strIDCT4x4Stage1(p0 + j + 0); + strIDCT4x4Stage1(p0 + j + 16); + } + } + + if (!bottom) + { + for (j = (left ? 0 : -128); j < (right ? 0 : 128); j += 64) + { + strIDCT4x4Stage1(p1 + j + 0); + strIDCT4x4Stage1(p1 + j + 16); + } + } + + //================================ + // first level inverse overlap + if (OL_NONE != olOverlap) + { + if (leftORright) + { + j = left ? 0 + 10 : -64 + 14; + if (!top) + { + p = p0 + 16 + j; + strPost4(p + 0, p - 2, p + 6, p + 8); + strPost4(p + 1, p - 1, p + 7, p + 9); + strPost4(p + 16, p + 14, p + 22, p + 24); + strPost4(p + 17, p + 15, p + 23, p + 25); + p = NULL; + } + if (!bottom) + { + p = p1 + j; + strPost4(p + 0, p - 2, p + 6, p + 8); + strPost4(p + 1, p - 1, p + 7, p + 9); + p = NULL; + } + if (!topORbottom) + { + strPost4(p0 + 48 + j + 0, p0 + 48 + j - 2, p1 - 10 + j, p1 - 8 + j); + strPost4(p0 + 48 + j + 1, p0 + 48 + j - 1, p1 - 9 + j, p1 - 7 + j); + } + } + + if (top) + { + for (j = (left ? 0 : -192); j < (right ? -64 : 64); j += 64) + { + p = p1 + j; + strPost4(p + 5, p + 4, p + 64, p + 65); + strPost4(p + 7, p + 6, p + 66, p + 67); + p = NULL; + + strPost4x4Stage1(p1 + j, 0, iHPQP, bHPAbsent); + } + } + else if (bottom) + { + for (j = (left ? 0 : -192); j < (right ? -64 : 64); j += 64) + { + strPost4x4Stage1(p0 + 16 + j, 0, iHPQP, bHPAbsent); + strPost4x4Stage1(p0 + 32 + j, 0, iHPQP, bHPAbsent); + + p = p0 + 48 + j; + strPost4(p + 15, p + 14, p + 74, p + 75); + strPost4(p + 13, p + 12, p + 72, p + 73); + p = NULL; + } + } + else + { + for (j = (left ? 0 : -192); j < (right ? -64 : 64); j += 64) + { + strPost4x4Stage1(p0 + 16 + j, 0, iHPQP, bHPAbsent); + strPost4x4Stage1(p0 + 32 + j, 0, iHPQP, bHPAbsent); + strPost4x4Stage1Split(p0 + 48 + j, p1 + j, 0, iHPQP, bHPAbsent); + strPost4x4Stage1(p1 + j, 0, iHPQP, bHPAbsent); + } + } + } + + if(pSC->WMII.cPostProcStrength > 0 && (!topORleft)) + postProcBlock(pSC->pPostProcInfo, p0, p1, mbX, i, qp[i]); // destairing and first stage deblocking + } + + //================================================================ + // 420_UV + for (i = 0; i < (YUV_420 == cfColorFormat? 2U : 0U) && tScale < 16; ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[1 + i];//(0 == i ? pSC->pU0 : pSC->pV0); + PixelI* const p1 = pSC->p1MBbuffer[1 + i];//(0 == i ? pSC->pU1 : pSC->pV1); + + Int iHPQP = 255; + if (!bHPAbsent) + iHPQP = pSC->pTile[pSC->cTileColumn].pQuantizerHP[i][pSC->MBInfo.iQIndexHP].iQP; + + //======================================== + // second level inverse transform (420_UV) + if (!bottomORright) + { + if (!pSC->m_param.bScaledArith) { + strDCT2x2dn(p1, p1 + 32, p1 + 16, p1 + 48); + } + else { + strDCT2x2dnDec(p1, p1 + 32, p1 + 16, p1 + 48); + } + } + + //======================================== + // second level inverse overlap (420_UV) + if (OL_TWO == olOverlap) + { + if (leftORright && !topORbottom) + { + j = (left ? 0 : -32); + strPost2(p0 + j + 16, p1 + j); + } + + if (!leftORright) + { + if (topORbottom) + { + p = (top ? p1 : p0 + 16); + strPost2(p - 32, p); + p = NULL; + } + else{ + strPost2x2(p0 - 16, p0 + 16, p1 - 32, p1); + } + } + } + + //======================================== + // first level inverse transform (420_UV) + if(tScale >= 4) // bypass first level transform for 4:1 and smaller thumbnail + continue; + + if (!top) + { + for (j = (left ? 16 : -16); j < (right ? 16 : 48); j += 32) + { + strIDCT4x4Stage1(p0 + j); + } + } + + if (!bottom) + { + for (j = (left ? 0 : -32); j < (right ? 0 : 32); j += 32) + { + strIDCT4x4Stage1(p1 + j); + } + } + + //======================================== + // first level inverse overlap (420_UV) + if (OL_NONE != olOverlap) + { + if(!left && !top) + { + if (bottom) + { + for (j = -48; j < (right ? -16 : 16); j += 32) + { + p = p0 + j; + strPost4(p + 15, p + 14, p + 42, p + 43); + strPost4(p + 13, p + 12, p + 40, p + 41); + p = NULL; + } + } + else + { + for (j = -48; j < (right ? -16 : 16); j += 32) + { + strPost4x4Stage1Split(p0 + j, p1 - 16 + j, 32, iHPQP, bHPAbsent); + } + } + + if (right) + { + if (!bottom) + { + strPost4(p0 - 2 , p0 - 4 , p1 - 28, p1 - 26); + strPost4(p0 - 1 , p0 - 3 , p1 - 27, p1 - 25); + } + + strPost4(p0 - 18, p0 - 20, p0 - 12, p0 - 10); + strPost4(p0 - 17, p0 - 19, p0 - 11, p0 - 9); + } + else + { + strPost4x4Stage1(p0 - 32, 32, iHPQP, bHPAbsent); + } + + strPost4x4Stage1(p0 - 64, 32, iHPQP, bHPAbsent); + } + else if (top) + { + for (j = (left ? 0: -64); j < (right ? -32: 0); j += 32) + { + p = p1 + j + 4; + strPost4(p + 1, p + 0, p + 28, p + 29); + strPost4(p + 3, p + 2, p + 30, p + 31); + p = NULL; + } + } + else if (left) + { + if (!bottom) + { + strPost4(p0 + 26, p0 + 24, p1 + 0, p1 + 2); + strPost4(p0 + 27, p0 + 25, p1 + 1, p1 + 3); + } + + strPost4(p0 + 10, p0 + 8, p0 + 16, p0 + 18); + strPost4(p0 + 11, p0 + 9, p0 + 17, p0 + 19); + } + } + } + + //================================================================ + // 422_UV + for (i = 0; i < (YUV_422 == cfColorFormat? 2U : 0U) && tScale < 16; ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[1 + i];//(0 == i ? pSC->pU0 : pSC->pV0); + PixelI* const p1 = pSC->p1MBbuffer[1 + i];//(0 == i ? pSC->pU1 : pSC->pV1); + + Int iHPQP = 255; + if (!bHPAbsent) + iHPQP = pSC->pTile[pSC->cTileColumn].pQuantizerHP[i][pSC->MBInfo.iQIndexHP].iQP; + + //======================================== + // second level inverse transform (422_UV) + if ((!bottomORright) && pSC->m_Dparam->cThumbnailScale < 16) + { + // 1D lossless HT + p1[0] -= ((p1[32] + 1) >> 1); + p1[32] += p1[0]; + + if (!pSC->m_param.bScaledArith) { + strDCT2x2dn(p1 + 0, p1 + 64, p1 + 16, p1 + 80); + strDCT2x2dn(p1 + 32, p1 + 96, p1 + 48, p1 + 112); + } + else { + strDCT2x2dnDec(p1 + 0, p1 + 64, p1 + 16, p1 + 80); + strDCT2x2dnDec(p1 + 32, p1 + 96, p1 + 48, p1 + 112); + } + } + + //======================================== + // second level inverse overlap (422_UV) + if (OL_TWO == olOverlap) + { + if (!bottom) + { + if (leftORright) + { + if (!top) + { + j = (left ? 0 : -64); + strPost2(p0 + 48 + j, p1 + j); + } + + j = (left ? 16 : -48); + strPost2(p1 + j, p1 + j + 16); + } + else + { + if (top) + { + strPost2(p1 - 64, p1); + } + else + { + strPost2x2(p0 - 16, p0 + 48, p1 - 64, p1); + } + + strPost2x2(p1 - 48, p1 + 16, p1 - 32, p1 + 32); + } + } + else if (!leftORright) + { + strPost2(p0 - 16, p0 + 48); + } + } + + //======================================== + // first level inverse transform (422_UV) + if(tScale >= 4) // bypass first level transform for 4:1 and smaller thumbnail + continue; + + if (!top) + { + for (j = (left ? 48 : -16); j < (right ? 48 : 112); j += 64) + { + strIDCT4x4Stage1(p0 + j); + } + } + + if (!bottom) + { + for (j = (left ? 0 : -64); j < (right ? 0 : 64); j += 64) + { + strIDCT4x4Stage1(p1 + j + 0); + strIDCT4x4Stage1(p1 + j + 16); + strIDCT4x4Stage1(p1 + j + 32); + } + } + + //======================================== + // first level inverse overlap (422_UV) + if (OL_NONE != olOverlap) + { + if (!top) + { + if (leftORright) + { + j = (left ? 32 + 10 : -32 + 14); + + p = p0 + j; + strPost4(p + 0, p - 2, p + 6, p + 8); + strPost4(p + 1, p - 1, p + 7, p + 9); + + p = NULL; + } + + for (j = (left ? 0 : -128); j < (right ? -64 : 0); j += 64) + { + strPost4x4Stage1(p0 + j + 32, 0, iHPQP, bHPAbsent); + } + } + + if (!bottom) + { + if (leftORright) + { + j = (left ? 0 + 10 : -64 + 14); + + p = p1 + j; + strPost4(p + 0, p - 2, p + 6, p + 8); + strPost4(p + 1, p - 1, p + 7, p + 9); + + p += 16; + strPost4(p + 0, p - 2, p + 6, p + 8); + strPost4(p + 1, p - 1, p + 7, p + 9); + + p = NULL; + } + + for (j = (left ? 0 : -128); j < (right ? -64 : 0); j += 64) + { + strPost4x4Stage1(p1 + j + 0, 0, iHPQP, bHPAbsent); + strPost4x4Stage1(p1 + j + 16, 0, iHPQP, bHPAbsent); + } + } + + if (topORbottom) + { + p = (top ? p1 + 5 : p0 + 48 + 13); + for (j = (left ? 0 : -128); j < (right ? -64 : 0); j += 64) + { + strPost4(p + j + 0, p + j - 1, p + j + 59, p + j + 60); + strPost4(p + j + 2, p + j + 1, p + j + 61, p + j + 62); + } + p = NULL; + } + else + { + if (leftORright) + { + j = (left ? 0 + 0 : -64 + 4); + strPost4(p0 + j + 48 + 10 + 0, p0 + j + 48 + 10 - 2, p1 + j + 0, p1 + j + 2); + strPost4(p0 + j + 48 + 10 + 1, p0 + j + 48 + 10 - 1, p1 + j + 1, p1 + j + 3); + } + + for (j = (left ? 0 : -128); j < (right ? -64 : 0); j += 64) + { + strPost4x4Stage1Split(p0 + j + 48, p1 + j + 0, 0, iHPQP, bHPAbsent); + } + } + } + } + + return ICERR_OK; +} + +Int invTransformMacroblock_alteredOperators_hard(CWMImageStrCodec * pSC) +{ + const OVERLAP olOverlap = pSC->WMISCP.olOverlap; + const COLORFORMAT cfColorFormat = pSC->m_param.cfColorFormat; + // const BITDEPTH_BITS bdBitDepth = pSC->WMII.bdBitDepth; + const Bool left = (pSC->cColumn == 0), right = (pSC->cColumn == pSC->cmbWidth); + const Bool top = (pSC->cRow == 0), bottom = (pSC->cRow == pSC->cmbHeight); + const Bool topORbottom = (top || bottom), leftORright = (left || right); + const Bool topORleft = (top || left), bottomORright = (bottom || right); + Bool leftAdjacentColumn = (pSC->cColumn == 1), rightAdjacentColumn = (pSC->cColumn == pSC->cmbWidth - 1); + // Bool topAdjacentRow = (pSC->cRow == 1), bottomAdjacentRow = (pSC->cRow == pSC->cmbHeight - 1); + const size_t mbWidth = pSC->cmbWidth; + PixelI * p = NULL;// * pt = NULL; + size_t i; + const size_t iChannels = (cfColorFormat == YUV_420 || cfColorFormat == YUV_422) ? 1 : pSC->m_param.cNumChannels; + const size_t tScale = pSC->m_Dparam->cThumbnailScale; + Int j = 0; + + Int qp[MAX_CHANNELS], dcqp[MAX_CHANNELS], iStrength = (1 << pSC->WMII.cPostProcStrength); + // ERR_CODE result = ICERR_OK; + +#define mbX pSC->mbX +#define mbY pSC->mbY +#define tileX pSC->tileX +#define tileY pSC->tileY +#define bVertTileBoundary pSC->bVertTileBoundary +#define bHoriTileBoundary pSC->bHoriTileBoundary +#define bOneMBLeftVertTB pSC->bOneMBLeftVertTB +#define bOneMBRightVertTB pSC->bOneMBRightVertTB +#define iPredBefore pSC->iPredBefore +#define iPredAfter pSC->iPredAfter + + if (pSC->WMISCP.bUseHardTileBoundaries) { + //Add tile location information + if (pSC->cColumn == 0) { + bVertTileBoundary = FALSE; + tileY = 0; + } + bOneMBLeftVertTB = bOneMBRightVertTB = FALSE; + if(tileY > 0 && tileY <= pSC->WMISCP.cNumOfSliceMinus1H && (pSC->cColumn - 1) == pSC->WMISCP.uiTileY[tileY]) + bOneMBRightVertTB = TRUE; + if(tileY < pSC->WMISCP.cNumOfSliceMinus1H && pSC->cColumn == pSC->WMISCP.uiTileY[tileY + 1]) { + bVertTileBoundary = TRUE; + tileY++; + } + else + bVertTileBoundary = FALSE; + if(tileY < pSC->WMISCP.cNumOfSliceMinus1H && (pSC->cColumn + 1) == pSC->WMISCP.uiTileY[tileY + 1]) + bOneMBLeftVertTB = TRUE; + + if (pSC->cRow == 0) { + bHoriTileBoundary = FALSE; + tileX = 0; + } + else if(mbY != pSC->cRow && tileX < pSC->WMISCP.cNumOfSliceMinus1V && pSC->cRow == pSC->WMISCP.uiTileX[tileX + 1]) { + bHoriTileBoundary = TRUE; + tileX++; + } + else if(mbY != pSC->cRow) + bHoriTileBoundary = FALSE; + } + else { + bVertTileBoundary = FALSE; + bHoriTileBoundary = FALSE; + bOneMBLeftVertTB = FALSE; + bOneMBRightVertTB = FALSE; + } + mbX = pSC->cColumn, mbY = pSC->cRow; + + if(pSC->WMII.cPostProcStrength > 0){ + // threshold for post processing + for(i = 0; i < iChannels; i ++){ + qp[i] = pSC->pTile[pSC->cTileColumn].pQuantizerLP[i][pSC->MBInfo.iQIndexLP].iQP * iStrength * (olOverlap == OL_NONE ? 2 : 1); + dcqp[i] = pSC->pTile[pSC->cTileColumn].pQuantizerDC[i][0].iQP * iStrength; + } + + if(left) // a new MB row + slideOneMBRow(pSC->pPostProcInfo, pSC->m_param.cNumChannels, mbWidth, top, bottom); // previous current row becomes previous row + } + + //================================================================ + // 400_Y, 444_YUV + for (i = 0; i < iChannels && tScale < 16; ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[i]; + PixelI* const p1 = pSC->p1MBbuffer[i]; + + //================================ + // second level inverse transform + if (!bottomORright) + { + if(pSC->WMII.cPostProcStrength > 0) + updatePostProcInfo(pSC->pPostProcInfo, p1, mbX, i); // update postproc info before IDCT + + strIDCT4x4Stage2(p1); + if (pSC->m_param.bScaledArith) { + strNormalizeDec(p1, (i != 0)); + } + } + + //================================ + // second level inverse overlap + if (OL_TWO == olOverlap) + { + /* Corner operations */ + if ((top || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPost4_alternate(p1 + 0, p1 + 64, p1 + 0 + 16, p1 + 64 + 16); + if ((top || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPost4_alternate(p1 - 128, p1 - 64, p1 - 128 + 16, p1 - 64 + 16); + if ((bottom || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPost4_alternate(p0 + 32, p0 + 96, p0 + 32 + 16, p0 + 96 + 16); + if ((bottom || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPost4_alternate(p0 - 96, p0 - 32, p0 - 96 + 16, p0 - 32 + 16); + if ((leftORright || bVertTileBoundary) && (!topORbottom && !bHoriTileBoundary)) + { + if (left || bVertTileBoundary) { + j = 0; + strPost4_alternate(p0 + j + 32, p0 + j + 48, p1 + j + 0, p1 + j + 16); + strPost4_alternate(p0 + j + 96, p0 + j + 112, p1 + j + 64, p1 + j + 80); + } + if (right || bVertTileBoundary) { + j = -128; + strPost4_alternate(p0 + j + 32, p0 + j + 48, p1 + j + 0, p1 + j + 16); + strPost4_alternate(p0 + j + 96, p0 + j + 112, p1 + j + 64, p1 + j + 80); + } + } + + if (!leftORright) + { + if ((topORbottom || bHoriTileBoundary) && !bVertTileBoundary) + { + if (top || bHoriTileBoundary) { + p = p1; + strPost4_alternate(p - 128, p - 64, p + 0, p + 64); + strPost4_alternate(p - 112, p - 48, p + 16, p + 80); + p = NULL; + } + if (bottom || bHoriTileBoundary) { + p = p0 + 32; + strPost4_alternate(p - 128, p - 64, p + 0, p + 64); + strPost4_alternate(p - 112, p - 48, p + 16, p + 80); + p = NULL; + } + } + + if (!topORbottom && !bHoriTileBoundary && !bVertTileBoundary) + strPost4x4Stage2Split_alternate(p0, p1); + } + } + + if(pSC->WMII.cPostProcStrength > 0) + postProcMB(pSC->pPostProcInfo, p0, p1, mbX, i, dcqp[i]); // second stage deblocking + + //================================ + // first level inverse transform + if(tScale >= 4) // bypass first level transform for 4:1 and smaller thumbnail + continue; + + if (!top) + { + for (j = (left ? 32 : -96); j < (right ? 32 : 160); j += 64) + { + strIDCT4x4Stage1(p0 + j + 0); + strIDCT4x4Stage1(p0 + j + 16); + } + } + + if (!bottom) + { + for (j = (left ? 0 : -128); j < (right ? 0 : 128); j += 64) + { +// if(tScale == 2 && bdBitDepth != BD_1){ +// MIPgen(p1 + j + 0); +// MIPgen(p1 + j + 16); +// } + strIDCT4x4Stage1(p1 + j + 0); + strIDCT4x4Stage1(p1 + j + 16); + } + } + + //================================ + // first level inverse overlap + if (OL_NONE != olOverlap) + { + if (leftORright || bVertTileBoundary) + { + /* Corner operations */ + if ((top || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPost4_alternate(p1 + 0, p1 + 1, p1 + 2, p1 + 3); + if ((top || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPost4_alternate(p1 - 59, p1 - 60, p1 - 57, p1 - 58); + if ((bottom || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPost4_alternate(p0 + 48 + 10, p0 + 48 + 11, p0 + 48 + 8, p0 + 48 + 9); + if ((bottom || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPost4_alternate(p0 - 1, p0 - 2, p0 - 3, p0 - 4); + if (left || bVertTileBoundary) { + j = 0 + 10; + if (!top) + { + p = p0 + 16 + j; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + strPost4_alternate(p + 16, p + 14, p + 22, p + 24); + strPost4_alternate(p + 17, p + 15, p + 23, p + 25); + p = NULL; + } + if (!bottom) + { + p = p1 + j; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + p = NULL; + } + if (!topORbottom && !bHoriTileBoundary) + { + strPost4_alternate(p0 + 48 + j + 0, p0 + 48 + j - 2, p1 - 10 + j, p1 - 8 + j); + strPost4_alternate(p0 + 48 + j + 1, p0 + 48 + j - 1, p1 - 9 + j, p1 - 7 + j); + } + } + if (right || bVertTileBoundary) { + j = -64 + 14; + if (!top) + { + p = p0 + 16 + j; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + strPost4_alternate(p + 16, p + 14, p + 22, p + 24); + strPost4_alternate(p + 17, p + 15, p + 23, p + 25); + p = NULL; + } + if (!bottom) + { + p = p1 + j; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + p = NULL; + } + if (!topORbottom && !bHoriTileBoundary) + { + strPost4_alternate(p0 + 48 + j + 0, p0 + 48 + j - 2, p1 - 10 + j, p1 - 8 + j); + strPost4_alternate(p0 + 48 + j + 1, p0 + 48 + j - 1, p1 - 9 + j, p1 - 7 + j); + } + } + } + + if (top || bHoriTileBoundary) + { + for (j = (left ? 0 : -192); j < (right ? -64 : 64); j += 64) + { + if (!bVertTileBoundary || j != -64) { + p = p1 + j; + strPost4_alternate(p + 5, p + 4, p + 64, p + 65); + strPost4_alternate(p + 7, p + 6, p + 66, p + 67); + p = NULL; + + strPost4x4Stage1_alternate(p1 + j, 0); + } + } + } + + if (bottom || bHoriTileBoundary) + { + for (j = (left ? 0 : -192); j < (right ? -64 : 64); j += 64) + { + if (!bVertTileBoundary || j != -64) { + strPost4x4Stage1_alternate(p0 + 16 + j, 0); + strPost4x4Stage1_alternate(p0 + 32 + j, 0); + + p = p0 + 48 + j; + strPost4_alternate(p + 15, p + 14, p + 74, p + 75); + strPost4_alternate(p + 13, p + 12, p + 72, p + 73); + p = NULL; + } + } + } + + if (!top && !bottom && !bHoriTileBoundary) + { + for (j = (left ? 0 : -192); j < (right ? -64 : 64); j += 64) + { + if (!bVertTileBoundary || j != -64) { + strPost4x4Stage1_alternate(p0 + 16 + j, 0); + strPost4x4Stage1_alternate(p0 + 32 + j, 0); + strPost4x4Stage1Split_alternate(p0 + 48 + j, p1 + j, 0); + strPost4x4Stage1_alternate(p1 + j, 0); + } + } + } + } + + if(pSC->WMII.cPostProcStrength > 0 && (!topORleft)) + postProcBlock(pSC->pPostProcInfo, p0, p1, mbX, i, qp[i]); // destairing and first stage deblocking + } + + //================================================================ + // 420_UV + for (i = 0; i < (YUV_420 == cfColorFormat? 2U : 0U) && tScale < 16; ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[1 + i];//(0 == i ? pSC->pU0 : pSC->pV0); + PixelI* const p1 = pSC->p1MBbuffer[1 + i];//(0 == i ? pSC->pU1 : pSC->pV1); + + //======================================== + // second level inverse transform (420_UV) + if (!bottomORright) + { + if (!pSC->m_param.bScaledArith) { + strDCT2x2dn(p1, p1 + 32, p1 + 16, p1 + 48); + } + else { + strDCT2x2dnDec(p1, p1 + 32, p1 + 16, p1 + 48); + } + } + + //======================================== + // second level inverse overlap (420_UV) + if (OL_TWO == olOverlap) + { + if ((leftAdjacentColumn || bOneMBRightVertTB) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p1 - 64 + 0, *(p1 - 64 + 32)); + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (top || bHoriTileBoundary)) + iPredBefore[i][0] = *(p1 + 0); + if ((right || bVertTileBoundary) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p1 - 64 + 32, iPredBefore[i][0]); + if ((leftAdjacentColumn || bOneMBRightVertTB) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p0 - 64 + 16, *(p0 - 64 + 48)); + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (bottom || bHoriTileBoundary)) + iPredBefore[i][1] = *(p0 + 16); + if ((right || bVertTileBoundary) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p0 - 64 + 48, iPredBefore[i][1]); + + if ((leftORright || bVertTileBoundary) && !topORbottom && !bHoriTileBoundary) + { + if (left || bVertTileBoundary) + strPost2_alternate(p0 + 0 + 16, p1 + 0); + if (right || bVertTileBoundary) + strPost2_alternate(p0 + -32 + 16, p1 + -32); + } + + if (!leftORright) + { + if ((topORbottom || bHoriTileBoundary) && !bVertTileBoundary) + { + if (top || bHoriTileBoundary) + strPost2_alternate(p1 - 32, p1); + if (bottom || bHoriTileBoundary) + strPost2_alternate(p0 + 16 - 32, p0 + 16); + } + else if (!topORbottom && !bHoriTileBoundary && !bVertTileBoundary) { + strPost2x2_alternate(p0 - 16, p0 + 16, p1 - 32, p1); + } + } + if ((leftAdjacentColumn || bOneMBRightVertTB) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p1 - 64 + 0, *(p1 - 64 + 32)); + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (top || bHoriTileBoundary)) + iPredAfter[i][0] = *(p1 + 0); + if ((right || bVertTileBoundary) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p1 - 64 + 32, iPredAfter[i][0]); + if ((leftAdjacentColumn || bOneMBRightVertTB) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p0 - 64 + 16, *(p0 - 64 + 48)); + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (bottom || bHoriTileBoundary)) + iPredAfter[i][1] = *(p0 + 16); + if ((right || bVertTileBoundary) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p0 - 64 + 48, iPredAfter[i][1]); + } + + //======================================== + // first level inverse transform (420_UV) + if(tScale >= 4) // bypass first level transform for 4:1 and smaller thumbnail + continue; + + if (!top) + { + // In order to allow correction operation of corner chroma overlap operators (fixed) + // processing of left most MB column must be delayed by one MB + // Thus left MB not processed until leftAdjacentColumn = 1 + for (j = ((left) ? 48 : ((leftAdjacentColumn || bOneMBRightVertTB) ? -48 : -16)); j < ((right || bVertTileBoundary) ? 16 : 48); j += 32) + { + strIDCT4x4Stage1(p0 + j); + } + } + + if (!bottom) + { + // In order to allow correction operation of corner chroma overlap operators (fixed) + // processing of left most MB column must be delayed by one MB + // Thus left MB not processed until leftAdjacentColumn = 1 + for (j = ((left) ? 32 : ((leftAdjacentColumn || bOneMBRightVertTB) ? -64 : -32)); j < ((right || bVertTileBoundary) ? 0 : 32); j += 32) + { + strIDCT4x4Stage1(p1 + j); + } + } + + //======================================== + // first level inverse overlap (420_UV) + if (OL_NONE != olOverlap) + { + /* Corner operations */ + /* Change because the top-left corner ICT will not have happened until leftAdjacentColumn ==1 */ + if ((top || bHoriTileBoundary) && (leftAdjacentColumn || bOneMBRightVertTB)) + strPost4_alternate(p1 - 64 + 0, p1 - 64 + 1, p1 - 64 + 2, p1 - 64 + 3); + if ((top || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPost4_alternate(p1 - 27, p1 - 28, p1 - 25, p1 - 26); + /* Change because the bottom-left corner ICT will not have happened until leftAdjacentColumn ==1 */ + if ((bottom || bHoriTileBoundary) && (leftAdjacentColumn || bOneMBRightVertTB)) + strPost4_alternate(p0 - 64 + 16 + 10, p0 - 64 + 16 + 11, p0 - 64 + 16 + 8, p0 - 64 + 16 + 9); + if ((bottom || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPost4_alternate(p0 - 1, p0 - 2, p0 - 3, p0 - 4); + if(!left && !top) + { + /* Change because the vertical 1-D overlap operations of the left edge pixels cannot be performed until leftAdjacentColumn ==1 */ + if (leftAdjacentColumn || bOneMBRightVertTB) + { + if (!bottom && !bHoriTileBoundary) + { + strPost4_alternate(p0 - 64 + 26, p0 - 64 + 24, p1 - 64 + 0, p1 - 64 + 2); + strPost4_alternate(p0 - 64 + 27, p0 - 64 + 25, p1 - 64 + 1, p1 - 64 + 3); + } + + strPost4_alternate(p0 - 64 + 10, p0 - 64 + 8, p0 - 64 + 16, p0 - 64 + 18); + strPost4_alternate(p0 - 64 + 11, p0 - 64 + 9, p0 - 64 + 17, p0 - 64 + 19); + } + if (bottom || bHoriTileBoundary) + { + p = p0 + -48; + strPost4_alternate(p + 15, p + 14, p + 42, p + 43); + strPost4_alternate(p + 13, p + 12, p + 40, p + 41); + p = NULL; + + if (!right && !bVertTileBoundary) + { + p = p0 + -16; + strPost4_alternate(p + 15, p + 14, p + 42, p + 43); + strPost4_alternate(p + 13, p + 12, p + 40, p + 41); + p = NULL; + } + } + else + { + strPost4x4Stage1Split_alternate(p0 + -48, p1 - 16 + -48, 32); + + if (!right && !bVertTileBoundary) + strPost4x4Stage1Split_alternate(p0 + -16, p1 - 16 + -16, 32); + } + + if (right || bVertTileBoundary) + { + if (!bottom && !bHoriTileBoundary) + { + strPost4_alternate(p0 - 2 , p0 - 4 , p1 - 28, p1 - 26); + strPost4_alternate(p0 - 1 , p0 - 3 , p1 - 27, p1 - 25); + } + + strPost4_alternate(p0 - 18, p0 - 20, p0 - 12, p0 - 10); + strPost4_alternate(p0 - 17, p0 - 19, p0 - 11, p0 - 9); + } + else + { + strPost4x4Stage1_alternate(p0 - 32, 32); + } + + strPost4x4Stage1_alternate(p0 - 64, 32); + } + + if (top || bHoriTileBoundary) + { + if (!left) + { + p = p1 + -64 + 4; + strPost4_alternate(p + 1, p + 0, p + 28, p + 29); + strPost4_alternate(p + 3, p + 2, p + 30, p + 31); + p = NULL; + } + + if (!left && !right && !bVertTileBoundary) + { + p = p1 + -32 + 4; + strPost4_alternate(p + 1, p + 0, p + 28, p + 29); + strPost4_alternate(p + 3, p + 2, p + 30, p + 31); + p = NULL; + } + } + } + } + + //================================================================ + // 422_UV + for (i = 0; i < (YUV_422 == cfColorFormat? 2U : 0U) && tScale < 16; ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[1 + i];//(0 == i ? pSC->pU0 : pSC->pV0); + PixelI* const p1 = pSC->p1MBbuffer[1 + i];//(0 == i ? pSC->pU1 : pSC->pV1); + + //======================================== + // second level inverse transform (422_UV) + if ((!bottomORright) && pSC->m_Dparam->cThumbnailScale < 16) + { + // 1D lossless HT + p1[0] -= ((p1[32] + 1) >> 1); + p1[32] += p1[0]; + + if (!pSC->m_param.bScaledArith) { + strDCT2x2dn(p1 + 0, p1 + 64, p1 + 16, p1 + 80); + strDCT2x2dn(p1 + 32, p1 + 96, p1 + 48, p1 + 112); + } + else { + strDCT2x2dnDec(p1 + 0, p1 + 64, p1 + 16, p1 + 80); + strDCT2x2dnDec(p1 + 32, p1 + 96, p1 + 48, p1 + 112); + } + } + + //======================================== + // second level inverse overlap (422_UV) + if (OL_TWO == olOverlap) + { + if ((leftAdjacentColumn || bOneMBRightVertTB) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p1 - 128 + 0, *(p1 - 128 + 64)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (top || bHoriTileBoundary)) + iPredBefore[i][0] = *(p1 + 0); + if ((right || bVertTileBoundary) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p1 - 128 + 64, iPredBefore[i][0]); + + if ((leftAdjacentColumn || bOneMBRightVertTB) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p0 - 128 + 48, *(p0 - 128 + 112)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (bottom || bHoriTileBoundary)) + iPredBefore[i][1] = *(p0 + 48); + if ((right || bVertTileBoundary) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p0 - 128 + 112, iPredBefore[i][1]); + + if (!bottom) + { + if (leftORright || bVertTileBoundary) + { + if (!top && !bHoriTileBoundary) + { + if (left || bVertTileBoundary) + strPost2_alternate(p0 + 48 + 0, p1 + 0); + + if (right || bVertTileBoundary) + strPost2_alternate(p0 + 48 + -64, p1 + -64); + } + + if (left || bVertTileBoundary) + strPost2_alternate(p1 + 16, p1 + 16 + 16); + + if (right || bVertTileBoundary) + strPost2_alternate(p1 + -48, p1 + -48 + 16); + } + + if (!leftORright && !bVertTileBoundary) + { + if (top || bHoriTileBoundary) + strPost2_alternate(p1 - 64, p1); + else + strPost2x2_alternate(p0 - 16, p0 + 48, p1 - 64, p1); + + strPost2x2_alternate(p1 - 48, p1 + 16, p1 - 32, p1 + 32); + } + } + + if ((bottom || bHoriTileBoundary) && (!leftORright && !bVertTileBoundary)) + strPost2_alternate(p0 - 16, p0 + 48); + + if ((leftAdjacentColumn || bOneMBRightVertTB) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p1 - 128 + 0, *(p1 - 128 + 64)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (top || bHoriTileBoundary)) + iPredAfter[i][0] = *(p1 + 0); + if ((right || bVertTileBoundary) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p1 - 128 + 64, iPredAfter[i][0]); + + if ((leftAdjacentColumn || bOneMBRightVertTB) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p0 - 128 + 48, *(p0 - 128 + 112)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (bottom || bHoriTileBoundary)) + iPredAfter[i][1] = *(p0 + 48); + if ((right || bVertTileBoundary) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p0 - 128 + 112, iPredAfter[i][1]); + } + + //======================================== + // first level inverse transform (422_UV) + if(tScale >= 4) // bypass first level transform for 4:1 and smaller thumbnail + continue; + + if (!top) + { + // Need to delay processing of left column until leftAdjacentColumn = 1 for corner overlap operators + // Since 422 has no vertical downsampling, no top MB delay of processing is necessary + for (j = (left ? 112 : ((leftAdjacentColumn || bOneMBRightVertTB) ? -80 : -16)); j < ((right || bVertTileBoundary) ? 48 : 112); j += 64) + { + strIDCT4x4Stage1(p0 + j); + } + } + + if (!bottom) + { + // Need to delay processing of left column until leftAdjacentColumn = 1 for corner overlap operators + // Since 422 has no vertical downsampling, no top MB delay of processing is necessary + for (j = (left ? 64 : ((leftAdjacentColumn || bOneMBRightVertTB) ? -128 : -64)); j < ((right || bVertTileBoundary) ? 0 : 64); j += 64) + { + strIDCT4x4Stage1(p1 + j + 0); + strIDCT4x4Stage1(p1 + j + 16); + strIDCT4x4Stage1(p1 + j + 32); + } + } + + //======================================== + // first level inverse overlap (422_UV) + if (OL_NONE != olOverlap) + { + /* Corner operations */ + if ((top || bHoriTileBoundary) && (leftAdjacentColumn || bOneMBRightVertTB)) + strPost4_alternate(p1 - 128 + 0, p1 - 128 + 1, p1 - 128 + 2, p1 - 128 + 3); + if ((top || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPost4_alternate(p1 - 59, p1 - 60, p1 - 57, p1 - 58); + if ((bottom || bHoriTileBoundary) && (leftAdjacentColumn || bOneMBRightVertTB)) + strPost4_alternate(p0 - 128 + 48 + 10, p0 - 128 + 48 + 11, p0 - 128 + 48 + 8, p0 - 128 + 48 + 9); + if ((bottom || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPost4_alternate(p0 - 1, p0 - 2, p0 - 3, p0 - 4); + if (!top) + { + // Need to delay processing of left column until leftAdjacentColumn = 1 for corner overlap operators + if (leftAdjacentColumn || bOneMBRightVertTB) { + p = p0 + 32 + 10 - 128; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + p = NULL; + } + + if (right || bVertTileBoundary) { + p = p0 + -32 + 14; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + p = NULL; + } + + for (j = (left ? 0 : -128); j < ((right || bVertTileBoundary) ? -64 : 0); j += 64) + strPost4x4Stage1_alternate(p0 + j + 32, 0); + } + + if (!bottom) + { + // Need to delay processing of left column until leftAdjacentColumn = 1 for corner overlap operators + if (leftAdjacentColumn || bOneMBRightVertTB) + { + p = p1 + 0 + 10 - 128; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + p += 16; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + p = NULL; + } + + if (right || bVertTileBoundary) + { + p = p1 + -64 + 14; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + p += 16; + strPost4_alternate(p + 0, p - 2, p + 6, p + 8); + strPost4_alternate(p + 1, p - 1, p + 7, p + 9); + p = NULL; + } + + for (j = (left ? 0 : -128); j < ((right || bVertTileBoundary) ? -64 : 0); j += 64) + { + strPost4x4Stage1_alternate(p1 + j + 0, 0); + strPost4x4Stage1_alternate(p1 + j + 16, 0); + } + } + + if (topORbottom || bHoriTileBoundary) + { + if (top || bHoriTileBoundary) { + p = p1 + 5; + for (j = (left ? 0 : -128); j < ((right || bVertTileBoundary) ? -64 : 0); j += 64) + { + strPost4_alternate(p + j + 0, p + j - 1, p + j + 59, p + j + 60); + strPost4_alternate(p + j + 2, p + j + 1, p + j + 61, p + j + 62); + } + p = NULL; + } + + if (bottom || bHoriTileBoundary) { + p = p0 + 48 + 13; + for (j = (left ? 0 : -128); j < ((right || bVertTileBoundary) ? -64 : 0); j += 64) + { + strPost4_alternate(p + j + 0, p + j - 1, p + j + 59, p + j + 60); + strPost4_alternate(p + j + 2, p + j + 1, p + j + 61, p + j + 62); + } + p = NULL; + } + } + else + { + // Need to delay processing of left column until leftAdjacentColumn = 1 for corner overlap operators + if (leftAdjacentColumn || bOneMBRightVertTB) + { + j = 0 + 0 - 128; + strPost4_alternate(p0 + j + 48 + 10 + 0, p0 + j + 48 + 10 - 2, p1 + j + 0, p1 + j + 2); + strPost4_alternate(p0 + j + 48 + 10 + 1, p0 + j + 48 + 10 - 1, p1 + j + 1, p1 + j + 3); + } + + if (right || bVertTileBoundary) + { + j = -64 + 4; + strPost4_alternate(p0 + j + 48 + 10 + 0, p0 + j + 48 + 10 - 2, p1 + j + 0, p1 + j + 2); + strPost4_alternate(p0 + j + 48 + 10 + 1, p0 + j + 48 + 10 - 1, p1 + j + 1, p1 + j + 3); + } + + for (j = (left ? 0 : -128); j < ((right || bVertTileBoundary) ? -64 : 0); j += 64) + strPost4x4Stage1Split_alternate(p0 + j + 48, p1 + j + 0, 0); + } + } + } + + return ICERR_OK; +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strInvTransform.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strInvTransform.o new file mode 100644 index 0000000..fca304c Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strInvTransform.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strPredQuantDec.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strPredQuantDec.c new file mode 100644 index 0000000..74aca93 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strPredQuantDec.c @@ -0,0 +1,539 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strcodec.h" + +#define DEQUANT(iRaw, iQP) ((iRaw) * (iQP)) + +Void dequantizeBlock4x4(PixelI * pRec, Int * pOrg, const Int * pIndex, Int iQPLP) +{ + Int i; + + for(i = 1; i < 16; i ++) + pRec[pIndex[i]] = DEQUANT(pOrg[i], iQPLP); +} + +Void dequantizeBlock2x2(PixelI * pRec, Int * pOrg, Int iQPLP) +{ + pRec[32] = DEQUANT(pOrg[1], iQPLP); + pRec[16] = DEQUANT(pOrg[2], iQPLP); + pRec[48] = DEQUANT(pOrg[3], iQPLP); +} + +Void dequantizeBlock4x2(PixelI * pRec, Int * pOrg, Int iQPLP) +{ + pRec[ 64] = DEQUANT(pOrg[1], iQPLP); + pRec[ 16] = DEQUANT(pOrg[2], iQPLP); + pRec[ 80] = DEQUANT(pOrg[3], iQPLP); + pRec[ 32] = DEQUANT(pOrg[4], iQPLP); + pRec[ 96] = DEQUANT(pOrg[5], iQPLP); + pRec[ 48] = DEQUANT(pOrg[6], iQPLP); + pRec[112] = DEQUANT(pOrg[7], iQPLP); +} + + +Int dequantizeMacroblock(CWMImageStrCodec * pSC) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + CWMIMBInfo *pMBInfo = &pSC->MBInfo; + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + const size_t iChannels = pSC->m_param.cNumChannels; + size_t i; + + for(i = 0; i < iChannels; i ++){ + //dequantize DC + pSC->p1MBbuffer[i][0] = DEQUANT(pMBInfo->iBlockDC[i][0], pTile->pQuantizerDC[i]->iQP); + + // dequantize LP + if(pSC->WMISCP.sbSubband != SB_DC_ONLY) + if(i == 0 || (cf != YUV_422 && cf != YUV_420)) + dequantizeBlock4x4(pSC->p1MBbuffer[i] , pMBInfo->iBlockDC[i], dctIndex[2], pTile->pQuantizerLP[i][pMBInfo->iQIndexLP].iQP); + else if(cf == YUV_422) + dequantizeBlock4x2(pSC->p1MBbuffer[i], pMBInfo->iBlockDC[i], pTile->pQuantizerLP[i][pMBInfo->iQIndexLP].iQP); + else // 420 + dequantizeBlock2x2(pSC->p1MBbuffer[i], pMBInfo->iBlockDC[i], pTile->pQuantizerLP[i][pMBInfo->iQIndexLP].iQP); + } + + return ICERR_OK; +} + +/* frequency domain inverse DCAC prediction */ +Void predDCACDec(CWMImageStrCodec * pSC) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : (Int) pSC->m_param.cNumChannels; + CWMIMBInfo *pMBInfo = &(pSC->MBInfo); + size_t mbX = pSC->cColumn;// mbY = pSC->cRow; + Int iDCACPredMode = getDCACPredMode(pSC, mbX); + Int iDCPredMode = (iDCACPredMode & 0x3); + Int iADPredMode = (iDCACPredMode & 0xC); + PixelI * pOrg, * pRef; + Int ii; + + for(ii = 0; ii < iChannels; ii ++){ + pOrg = pMBInfo->iBlockDC[ii];//[dcBlkIdx + (i >> 4)]; // current DC block + + /* DC prediction */ + if(iDCPredMode == 1){ // predict DC from top + pOrg[0] += pSC->PredInfoPrevRow[ii][mbX].iDC; + } + else if(iDCPredMode == 0){ // predict DC from left + pOrg[0] += (pSC->PredInfo[ii] + mbX - 1)->iDC; + } + else if(iDCPredMode == 2){// predict DC from top&left + pOrg[0] += ((pSC->PredInfo[ii] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[ii] + mbX)->iDC) >> 1; + } + + /* AD prediction */ + if(iADPredMode == 4){// predict AD from top + pRef = (pSC->PredInfoPrevRow[ii] + mbX)->piAD; + pOrg[4] += pRef[3], pOrg[8] += pRef[4], pOrg[12] += pRef[5]; + } + else if(iADPredMode == 0){// predict AD from left + pRef = (pSC->PredInfo[ii] + mbX - 1)->piAD; + pOrg[1] += pRef[0], pOrg[2] += pRef[1], pOrg[3] += pRef[2]; + } + } + + if(cf == YUV_420){ + for(ii = 1; ii < 3; ii ++){ + pOrg = pMBInfo->iBlockDC[ii];//dcBlkIdx + ii]; // current DC block + + /* DC prediction */ + if(iDCPredMode == 1){ // predict DC from top + pOrg[0] += (pSC->PredInfoPrevRow[ii] + mbX)->iDC; + } + else if(iDCPredMode == 0){ // predict DC from left + pOrg[0] += (pSC->PredInfo[ii] + mbX - 1)->iDC; + } + else if(iDCPredMode == 2){ // predict DC from top&left + pOrg[0] += (((pSC->PredInfo[ii] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[ii] + mbX)->iDC + 1) >> 1); + } + + /* AD prediciton */ + if(iADPredMode == 4){// predict AD from top + pOrg[2] += (pSC->PredInfoPrevRow[ii] + mbX)->piAD[1]; + } + else if(iADPredMode == 0){// predict AD from left + pOrg[1] += (pSC->PredInfo[ii] + mbX - 1)->piAD[0]; + } + } + } + else if(cf == YUV_422){ + for(ii = 1; ii < 3; ii ++){ + pOrg = pMBInfo->iBlockDC[ii];//[dcBlkIdx + ii]; // current DC block + + /* DC prediciton */ + if(iDCPredMode == 1){ // predict DC from top + pOrg[0] += (pSC->PredInfoPrevRow[ii] + mbX)->iDC; + } + else if(iDCPredMode == 0){ // predict DC from left + pOrg[0] += (pSC->PredInfo[ii] + mbX - 1)->iDC; + } + else if(iDCPredMode == 2){ // predict DC from top&left + pOrg[0] += (((pSC->PredInfo[ii] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[ii] + mbX)->iDC + 1) >> 1); + } + + /* AD prediction */ + if(iADPredMode == 4){// predict AD from top + pOrg[4] += (pSC->PredInfoPrevRow[ii] + mbX)->piAD[4]; // AC of HT !!! + pOrg[2] += (pSC->PredInfoPrevRow[ii] + mbX)->piAD[3]; + pOrg[6] += pOrg[2]; + } + else if(iADPredMode == 0){// predict AD from left + pOrg[4] += (pSC->PredInfo[ii] + mbX - 1)->piAD[4]; // AC of HT !!! + pOrg[1] += (pSC->PredInfo[ii] + mbX - 1)->piAD[0]; + pOrg[5] += (pSC->PredInfo[ii] + mbX - 1)->piAD[2]; + } + else if(iDCPredMode == 1){ + pOrg[6] += pOrg[2]; + } + } + } + + pMBInfo->iOrientation = 2 - getACPredMode(pMBInfo, cf); +} + +/************************************************************************* + Frequency domain inverse AC prediction +*************************************************************************/ +Void predACDec(CWMImageStrCodec * pSC) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : (Int) pSC->m_param.cNumChannels; + // size_t mbX = pSC->cColumn, mbY = pSC->cRow; + CWMIMBInfo *pMBInfo = &pSC->MBInfo; + Int iACPredMode = 2 - pMBInfo->iOrientation; + PixelI * pOrg, * pRef; + Int i, j; + + /* AC prediction */ + for(i = 0; i < iChannels; i++){ + // prediction only happens inside MB + PixelI* pSrc = pSC->p1MBbuffer[i];//0 == i ? pSC->pY1 : (1 == i ? pSC->pU1 : pSC->pV1); + + switch (iACPredMode) + { + case 1: + { + // predict from top + static U8 blkIdx[] = {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15}; + + for (j = 0; j < sizeof(blkIdx) / sizeof(*blkIdx); ++j) + { + pOrg = pSrc + 16 * blkIdx[j]; + pRef = pOrg - 16; + + pOrg[ 2] += pRef[ 2]; + pOrg[10] += pRef[10]; + pOrg[ 9] += pRef[ 9]; + } + break; + } + + case 0: + // predict from left + for (j = 64; j < 256; j += 16) + { + pOrg = pSrc + j; + pRef = pOrg - 64; + + pOrg[1] += pRef[1]; + pOrg[5] += pRef[5]; + pOrg[6] += pRef[6]; + } + break; + + default: + // no prediction + break; + } + } + + if(cf == YUV_420){ + for(i = 16; i <= 20; i += 4){ + PixelI* pSrc = pSC->p1MBbuffer[(i >> 2) - 3];//16 == i ? pSC->pU1 : pSC->pV1; + + switch (iACPredMode) + { + case 1: + { + // predict from top + for (j = 1; j <= 3; j += 2) + { + pOrg = pSrc + 16 * j; + pRef = pOrg - 16; + + pOrg[ 2] += pRef[ 2]; + pOrg[10] += pRef[10]; + pOrg[ 9] += pRef[ 9]; + } + break; + } + + case 0: + // predict from left + for (j = 2; j <= 3; ++j) + { + pOrg = pSrc + 16 * j; + pRef = pOrg - 32; + + pOrg[1] += pRef[1]; + pOrg[5] += pRef[5]; + pOrg[6] += pRef[6]; + } + break; + + default: + // no prediction + break; + } + } + } + else if(cf == YUV_422){ + for(i = 16; i < 32; i += 8){ + PixelI* pSrc = pSC->p1MBbuffer[(i >> 3) - 1];//16 == i ? pSC->pU1 : pSC->pV1; + + switch (iACPredMode) + { + case 1: + { + // predict from top + for (j = 2; j < 8; j ++) + { + pOrg = pSrc + blkOffsetUV_422[j]; + pRef = pOrg - 16; + + pOrg[10] += pRef[10]; + pOrg[ 2] += pRef[ 2]; + pOrg[ 9] += pRef[ 9]; + } + break; + } + + case 0: + // predict from left + for (j = 1; j < 8; j += 2) + { + pOrg = pSrc + blkOffsetUV_422[j]; + pRef = pOrg - 64; + + pOrg[1] += pRef[1]; + pOrg[5] += pRef[5]; + pOrg[6] += pRef[6]; + } + break; + + default: + // no prediction + break; + } + } + } +} + +/************************************************************************* + CBP +*************************************************************************/ +static int NumOnes(int i) +{ + int retval = 0; + static const int g_Count[] = { 0,1,1,2, 1,2,2,3, 1,2,2,3, 2,3,3,4 }; + i = i & 0xffff; + while (i) { + retval += g_Count[i & 0xf]; + i >>= 4; + } + return retval; +} + +#define SATURATE32(x) if((unsigned int)(x + 16) >= 32) { if (x < 0) x = -16; else x = 15; } + +/* CBP prediction for 16 x 16 MB */ +/* block index */ +/* 0 1 4 5 */ +/* 2 3 6 7 */ +/* 8 9 12 13 */ +/* 10 11 14 15 */ +static Int predCBPCDec(CWMImageStrCodec * pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel) +{ + Int iNOrig; + const int iNDiff = AVG_NDIFF; + size_t c1 = c ? 1 : 0; + + UNREFERENCED_PARAMETER( mbY ); + + if (pModel->m_iState[c1] == 0) { + if(pSC->m_bCtxLeft) { + if (pSC->m_bCtxTop) { + iCBP ^= 1; + } + else { + Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP; + iCBP ^= (iTopCBP >> 10) & 1; // left: top(10) => 0 + } + } + else { + Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP; + iCBP ^= ((iLeftCBP >> 5) & 1); // left(5) => 0 + } + + iCBP ^= (0x02 & (iCBP << 1)); // 0 => 1 + iCBP ^= (0x10 & (iCBP << 3)); // 1 => 4 + iCBP ^= (0x20 & (iCBP << 1)); // 4 => 5 + + iCBP ^= ((iCBP & 0x33) << 2); + iCBP ^= ((iCBP & 0xcc) << 6); + iCBP ^= ((iCBP & 0x3300) << 2); + + } + else if (pModel->m_iState[c1] == 2) { + iCBP ^= 0xffff; + } + + iNOrig = NumOnes(iCBP); + + pModel->m_iCount0[c1] += iNOrig - iNDiff; + SATURATE32(pModel->m_iCount0[c1]); + + pModel->m_iCount1[c1] += 16 - iNOrig - iNDiff; + SATURATE32(pModel->m_iCount1[c1]); + + if (pModel->m_iCount0[c1] < 0) { + if (pModel->m_iCount0[c1] < pModel->m_iCount1[c1]) { + pModel->m_iState[c1] = 1; + } + else { + pModel->m_iState[c1] = 2; + } + } + else if (pModel->m_iCount1[c1] < 0) { + pModel->m_iState[c1] = 2; + } + else { + pModel->m_iState[c1] = 0; + } + return iCBP; +} + +static Int predCBPC420Dec(CWMImageStrCodec * pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel) +{ + Int iNOrig; + const int iNDiff = AVG_NDIFF; + + UNREFERENCED_PARAMETER( mbY ); + + if (pModel->m_iState[1] == 0) { + if(pSC->m_bCtxLeft) { + if (pSC->m_bCtxTop) { + iCBP ^= 1; + } + else { + Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP; + iCBP ^= (iTopCBP >> 2) & 1; // left: top(2) => 0 + } + } + else { + Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP; + iCBP ^= ((iLeftCBP >> 1) & 1); // left(1) => 0 + } + + iCBP ^= (0x02 & (iCBP << 1)); // 0 => 1 + iCBP ^= ((iCBP & 0x3) << 2); // [0 1] -> [2 3] + } + else if (pModel->m_iState[1] == 2) { + iCBP ^= 0xf; + } + + iNOrig = NumOnes(iCBP) * 4; + + pModel->m_iCount0[1] += iNOrig - iNDiff; + SATURATE32(pModel->m_iCount0[1]); + + pModel->m_iCount1[1] += 16 - iNOrig - iNDiff; + SATURATE32(pModel->m_iCount1[1]); + + if (pModel->m_iCount0[1] < 0) { + if (pModel->m_iCount0[1] < pModel->m_iCount1[1]) { + pModel->m_iState[1] = 1; + } + else { + pModel->m_iState[1] = 2; + } + } + else if (pModel->m_iCount1[1] < 0) { + pModel->m_iState[1] = 2; + } + else { + pModel->m_iState[1] = 0; + } + + return iCBP; +} + +static Int predCBPC422Dec(CWMImageStrCodec * pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel) +{ + Int iNOrig; + const int iNDiff = AVG_NDIFF; + + UNREFERENCED_PARAMETER( mbY ); + + if (pModel->m_iState[1] == 0) { + if(pSC->m_bCtxLeft) { + if (pSC->m_bCtxTop) { + iCBP ^= 1; + } + else { + Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP; + iCBP ^= (iTopCBP >> 6) & 1; // left: top(6) => 0 + } + } + else { + Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP; + iCBP ^= ((iLeftCBP >> 1) & 1); // left(1) => 0 + } + + iCBP ^= (iCBP & 0x1) << 1; // [0]->[1] + iCBP ^= (iCBP & 0x3) << 2; // [0 1]->[2 3] + iCBP ^= (iCBP & 0xc) << 2; // [2 3]->[4 5] + iCBP ^= (iCBP & 0x30) << 2; // [4 5]->[6 7] + } + else if (pModel->m_iState[1] == 2) { + iCBP ^= 0xff; + } + + iNOrig = NumOnes(iCBP) * 2; + + pModel->m_iCount0[1] += iNOrig - iNDiff; + SATURATE32(pModel->m_iCount0[1]); + + pModel->m_iCount1[1] += 16 - iNOrig - iNDiff; + SATURATE32(pModel->m_iCount1[1]); + + if (pModel->m_iCount0[1] < 0) { + if (pModel->m_iCount0[1] < pModel->m_iCount1[1]) { + pModel->m_iState[1] = 1; + } + else { + pModel->m_iState[1] = 2; + } + } + else if (pModel->m_iCount1[1] < 0) { + pModel->m_iState[1] = 2; + } + else { + pModel->m_iState[1] = 0; + } + + return iCBP; +} + + +/* Coded Block Pattern (CBP) prediction */ +Void predCBPDec(CWMImageStrCodec *pSC, CCodingContext *pContext) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const size_t iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : pSC->m_param.cNumChannels; + size_t i, mbX = pSC->cColumn, mbY = pSC->cRow; + CWMIMBInfo *pMBInfo = &(pSC->MBInfo); + + for (i = 0; i < iChannels; i++) { + (pSC->PredInfo[i] + mbX)->iCBP = pMBInfo->iCBP[i] = predCBPCDec(pSC, pMBInfo->iDiffCBP[i], mbX, mbY, i, &pContext->m_aCBPModel); // Y Channel + } + + if (cf == YUV_422){ + (pSC->PredInfo[1] + mbX)->iCBP = pMBInfo->iCBP[1] = predCBPC422Dec(pSC, pMBInfo->iDiffCBP[1], mbX, mbY, 1, &pContext->m_aCBPModel); + (pSC->PredInfo[2] + mbX)->iCBP = pMBInfo->iCBP[2] = predCBPC422Dec(pSC, pMBInfo->iDiffCBP[2], mbX, mbY, 2, &pContext->m_aCBPModel); + } + else if (cf == YUV_420) { + (pSC->PredInfo[1] + mbX)->iCBP = pMBInfo->iCBP[1] = predCBPC420Dec(pSC, pMBInfo->iDiffCBP[1], mbX, mbY, 1, &pContext->m_aCBPModel); + (pSC->PredInfo[2] + mbX)->iCBP = pMBInfo->iCBP[2] = predCBPC420Dec(pSC, pMBInfo->iDiffCBP[2], mbX, mbY, 2, &pContext->m_aCBPModel); + } + //} +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strPredQuantDec.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strPredQuantDec.o new file mode 100644 index 0000000..6883d91 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strPredQuantDec.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec.c new file mode 100644 index 0000000..e93b7eb --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec.c @@ -0,0 +1,3628 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include "strcodec.h" +#include "decode.h" +#include "strTransform.h" +#include +#include "perfTimer.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +#ifdef X86OPT_INLINE +#define _FORCEINLINE __forceinline +#else // X86OPT_INLINE +#define _FORCEINLINE +#endif // X86OPT_INLINE + +#if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_DEC) || defined(WMP_OPT_TRFM_DEC) +void StrDecOpt(CWMImageStrCodec* pSC); +#endif // OPT defined + +Int processMacroblockDec(CWMImageStrCodec *); + +U8 readQuantizerSB(U8 pQPIndex[MAX_CHANNELS], SimpleBitIO * pIO, size_t cChannel) +{ + U8 cChMode = 0; + + if(cChannel >= MAX_CHANNELS) + return 0; + + if(cChannel > 1) + cChMode = (U8)getBit32_SB(pIO, 2); // Channel mode + + pQPIndex[0] = (U8)getBit32_SB(pIO, 8); // Y + + if(cChMode == 1) // MIXED + pQPIndex[1] = (U8)getBit32_SB(pIO, 8); // UV + else if(cChMode > 0){ // INDEPENDENT + size_t i; + + for(i = 1; i < cChannel; i ++) +#pragma prefast(suppress: __WARNING_UNRELATED_LOOP_TERMINATION_NO_SIZEEXPR, "PREfast false alarm: 1 <= i < MAX_CHANNELS, no buffer over/underrun!") + pQPIndex[i] = (U8)getBit32_SB(pIO, 8); // UV + } + + return cChMode; +} + +U8 readQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], BitIOInfo * pIO, size_t cChannel, size_t iPos) +{ + U8 cChMode = 0; + + if(cChannel > 1) + cChMode = (U8)getBit16(pIO, 2); // Channel mode + + pQuantizer[0][iPos].iIndex = (U8)getBit16(pIO, 8); // Y + + if(cChMode == 1) // MIXED + pQuantizer[1][iPos].iIndex = (U8)getBit16(pIO, 8); // UV + else if(cChMode > 0){ // INDEPENDENT + size_t i; + + for(i = 1; i < cChannel; i ++) + pQuantizer[i][iPos].iIndex = (U8)getBit16(pIO, 8); // UV + } + + return cChMode; +} + +// packet header: 00000000 00000000 00000001 ?????xxx +// xxx: 000(spatial) 001(DC) 010(AD) 011(AC) 100(FL) 101-111(reserved) +// ?????: (iTileY * cNumOfSliceV + iTileX) % 32 +Int readPacketHeader(BitIOInfo * pIO, U8 ptPacketType, U8 pID) +{ + UNREFERENCED_PARAMETER( ptPacketType ); + UNREFERENCED_PARAMETER( pID ); + if(getBit16(pIO, 8) != 0 || getBit16(pIO, 8) != 0 || getBit16(pIO, 8) != 1) + return ICERR_ERROR; + getBit16(pIO, 8); + return ICERR_OK; +} + +Int readTileHeaderDC(CWMImageStrCodec * pSC, BitIOInfo * pIO) +{ + if((pSC->m_param.uQPMode & 1) != 0){ // not DC uniform + size_t iTile; + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + + if(pSC->cTileRow + pSC->cTileColumn == 0) // allocate DC QP info + for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++) + if(allocateQuantizer(pSC->pTile[iTile].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK) + return ICERR_ERROR; + + pTile->cChModeDC = readQuantizer(pTile->pQuantizerDC, pIO, pSC->m_param.cNumChannels, 0); + formatQuantizer(pTile->pQuantizerDC, pTile->cChModeDC, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith); + } + + return ICERR_OK; +} + +Int readTileHeaderLP(CWMImageStrCodec * pSC, BitIOInfo * pIO) +{ + if(pSC->WMISCP.sbSubband != SB_DC_ONLY && (pSC->m_param.uQPMode & 2) != 0){ // not LP uniform + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + U8 i; + + pTile->bUseDC = (getBit16(pIO, 1) == 1 ? TRUE : FALSE); + pTile->cBitsLP = 0; + pTile->cNumQPLP = 1; + + if(pSC->cTileRow > 0) + freeQuantizer(pTile->pQuantizerLP); + + if(pTile->bUseDC == TRUE){ + if(allocateQuantizer(pTile->pQuantizerLP, pSC->m_param.cNumChannels, pTile->cNumQPLP) != ICERR_OK) + return ICERR_ERROR; + useDCQuantizer(pSC, pSC->cTileColumn); + } + else{ + pTile->cNumQPLP = (U8)getBit16(pIO, 4) + 1; + pTile->cBitsLP = dquantBits(pTile->cNumQPLP); + + if(allocateQuantizer(pTile->pQuantizerLP, pSC->m_param.cNumChannels, pTile->cNumQPLP) != ICERR_OK) + return ICERR_ERROR; + + for(i = 0; i < pTile->cNumQPLP; i ++){ + pTile->cChModeLP[i] = readQuantizer(pTile->pQuantizerLP, pIO, pSC->m_param.cNumChannels, i); + formatQuantizer(pTile->pQuantizerLP, pTile->cChModeLP[i], pSC->m_param.cNumChannels, i, TRUE, pSC->m_param.bScaledArith); + } + } + } + + return ICERR_OK; +} + +Int readTileHeaderHP(CWMImageStrCodec * pSC, BitIOInfo * pIO) +{ + if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS && (pSC->m_param.uQPMode & 4) != 0){ // not HP uniform + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + U8 i; + + pTile->bUseLP = (getBit16(pIO, 1) == 1 ? TRUE : FALSE); + pTile->cBitsHP = 0; + pTile->cNumQPHP = 1; + + if(pSC->cTileRow > 0) + freeQuantizer(pTile->pQuantizerHP); + + if(pTile->bUseLP == TRUE){ + pTile->cNumQPHP = pTile->cNumQPLP; + if(allocateQuantizer(pTile->pQuantizerHP, pSC->m_param.cNumChannels, pTile->cNumQPHP) != ICERR_OK) + return ICERR_ERROR; + useLPQuantizer(pSC, pTile->cNumQPHP, pSC->cTileColumn); + } + else{ + pTile->cNumQPHP = (U8)getBit16(pIO, 4) + 1; + pTile->cBitsHP = dquantBits(pTile->cNumQPHP); + + if(allocateQuantizer(pTile->pQuantizerHP, pSC->m_param.cNumChannels, pTile->cNumQPHP) != ICERR_OK) + return ICERR_ERROR; + + for(i = 0; i < pTile->cNumQPHP; i ++){ + pTile->cChModeHP[i] = readQuantizer(pTile->pQuantizerHP, pIO, pSC->m_param.cNumChannels, i); + formatQuantizer(pTile->pQuantizerHP, pTile->cChModeHP[i], pSC->m_param.cNumChannels, i, FALSE, pSC->m_param.bScaledArith); + } + } + } + + return ICERR_OK; +} + +Int readPackets(CWMImageStrCodec * pSC) +{ + if(pSC->cColumn == 0 && pSC->cRow == pSC->WMISCP.uiTileY[pSC->cTileRow]){ // start of a new horizontal slice + size_t k; + + if (pSC->m_bSecondary) { + if(pSC->cNumBitIO > 0){ + for(k = 0; k <= pSC->WMISCP.cNumOfSliceMinus1V; k ++){ + // reset coding contexts + ResetCodingContextDec(&pSC->m_pCodingContext[k]); + } + } + else{ // for multiple decoding calls! + ResetCodingContextDec(&pSC->m_pCodingContext[0]); + } + } + else { + // get sizes of each packet and update index table + for(k = 0; k < pSC->cNumBitIO; k ++){ + if(pSC->ppWStream != NULL){ // new API + unsigned cBands = (pSC->WMISCP.bfBitstreamFormat == SPATIAL ? 1 : pSC->cSB); + struct WMPStream ** ppWS = pSC->ppWStream + (pSC->WMISCP.cNumOfSliceMinus1V + 1) * pSC->cTileRow * cBands + + k / cBands * cBands + (k % cBands); + + if(pSC->cTileRow > 0 && pSC->m_ppBitIO[k]->pWS != NULL) // attached to the same packet of the tile on top + detachISRead(pSC, pSC->m_ppBitIO[k]); // detach it + + if(ppWS[0] != NULL) + attachISRead(pSC->m_ppBitIO[k], ppWS[0], pSC); // need to attach it + } + else{ + if(pSC->cTileRow > 0) + detachISRead(pSC, pSC->m_ppBitIO[k]); + pSC->WMISCP.pWStream->SetPos(pSC->WMISCP.pWStream, pSC->pIndexTable[pSC->cNumBitIO * pSC->cTileRow + k] + pSC->cHeaderSize); + attachISRead(pSC->m_ppBitIO[k], pSC->WMISCP.pWStream, pSC); + } + } + + if(pSC->cNumBitIO == 0){ + detachISRead(pSC, pSC->pIOHeader); + if(pSC->ppWStream != NULL){// new API + attachISRead(pSC->pIOHeader, pSC->ppWStream[0], pSC); // need to attach it + } + else{ + pSC->WMISCP.pWStream->SetPos(pSC->WMISCP.pWStream, pSC->cHeaderSize); + attachISRead(pSC->pIOHeader, pSC->WMISCP.pWStream, pSC); + } + } + + for(k = 0; k <= pSC->WMISCP.cNumOfSliceMinus1V; k ++){ + U8 pID = (U8)((pSC->cTileRow * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + k) & 0x1F); + + // read packet header + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){ + BitIOInfo * pIO = (pSC->cNumBitIO == 0 ? pSC->pIOHeader : pSC->m_ppBitIO[k]); + + if(pIO->pWS == NULL || readPacketHeader(pIO, 0, pID) != ICERR_OK) + return ICERR_ERROR; + pSC->m_pCodingContext[k].m_iTrimFlexBits = (pSC->m_param.bTrimFlexbitsFlag) ? getBit16(pIO, 4) : 0; + } + else{ + if(pSC->m_ppBitIO[k * pSC->cSB + 0] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 0], 1, pID) != ICERR_OK) + return ICERR_ERROR; + if(pSC->cSB > 1){ + if(pSC->m_ppBitIO[k * pSC->cSB + 1] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 1], 2, pID) != ICERR_OK) + return ICERR_ERROR; + } + if(pSC->cSB > 2){ + if(pSC->m_ppBitIO[k * pSC->cSB + 2] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 2], 3, pID) != ICERR_OK) + return ICERR_ERROR; +// readTileHeaderHP(pSC, pSC->m_ppBitIO[k * pSC->cSB + 2]); + } + if(pSC->cSB > 3){ + if(pSC->m_ppBitIO[k * pSC->cSB + 3] == NULL) + return ICERR_ERROR; + readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 3], 4, pID); // bad flexbits packet doesn't generate an error + pSC->m_pCodingContext[k].m_iTrimFlexBits = (pSC->m_param.bTrimFlexbitsFlag) ? getBit16(pSC->m_ppBitIO[k * pSC->cSB + 3], 4) : 0; + } + } + + // reset coding contexts + ResetCodingContextDec(&pSC->m_pCodingContext[k]); + } + } + } + + if(pSC->m_bCtxLeft && pSC->m_bCtxTop && pSC->m_bSecondary == FALSE){ + CCodingContext *pContext = &pSC->m_pCodingContext[pSC->cTileColumn]; + + readTileHeaderDC(pSC, pContext->m_pIODC); + if(pSC->m_pNextSC != NULL) + readTileHeaderDC(pSC->m_pNextSC, pContext->m_pIODC); + if(pSC->cSB > 1){ + readTileHeaderLP(pSC, pContext->m_pIOLP); + if(pSC->m_pNextSC != NULL) + readTileHeaderLP(pSC->m_pNextSC, pContext->m_pIOLP); + } + if(pSC->cSB > 2){ + readTileHeaderHP(pSC, pContext->m_pIOAC); + if(pSC->m_pNextSC != NULL) + readTileHeaderHP(pSC->m_pNextSC, pContext->m_pIOAC); + } + } + + return ICERR_OK; +} + +/* inverse transform and overlap possible part of a macroblock */ +Int processMacroblockDec(CWMImageStrCodec * pSC) +{ + const OVERLAP olOverlap = pSC->WMISCP.olOverlap; + // const Bool left = (pSC->cColumn == 0); + const Bool /*top = (pSC->cRow == 0),*/ bottom = (pSC->cRow == pSC->cmbHeight); + const Bool bottomORright = (bottom || pSC->cColumn == pSC->cmbWidth); + // const size_t mbWidth = pSC->cmbWidth, mbX = pSC->cColumn; + // Int iQIndex = 0; + ERR_CODE result = ICERR_OK; + size_t j, jend = (pSC->m_pNextSC != NULL); + + for (j = 0; j <= jend; j++) { + if(!bottomORright){ + CCodingContext *pContext; + + getTilePos(pSC, pSC->cColumn, pSC->cRow); + + if(jend){ + pSC->m_pNextSC->cTileColumn = pSC->cTileColumn; + pSC->m_pNextSC->cTileRow = pSC->cTileRow; + } + + pContext = &pSC->m_pCodingContext[pSC->cTileColumn]; + + if(readPackets(pSC) != ICERR_OK) + return ICERR_ERROR; + + // check if we need to do entropy decode + if(!pSC->m_Dparam->bDecodeFullFrame){ + if(pSC->cColumn == pSC->WMISCP.uiTileX[pSC->cTileColumn]){ // switching to a new tile + size_t rLeft = pSC->m_Dparam->cROILeftX, rRight = pSC->m_Dparam->cROIRightX; + size_t rTop = pSC->m_Dparam->cROITopY, rBottom = pSC->m_Dparam->cROIBottomY; + size_t rExt = (olOverlap == OL_NONE ? 0 : olOverlap == OL_ONE ? 2 : 10); + size_t tLeft = pSC->cColumn * 16, tTop = pSC->WMISCP.uiTileY[pSC->cTileRow] * 16; + size_t tRight = (pSC->cTileColumn != pSC->WMISCP.cNumOfSliceMinus1V ? pSC->WMISCP.uiTileX[pSC->cTileColumn + 1] : pSC->cmbWidth) * 16; + size_t tBottom = (pSC->cTileRow != pSC->WMISCP.cNumOfSliceMinus1H ? pSC->WMISCP.uiTileY[pSC->cTileRow + 1] : pSC->cmbHeight) * 16; + + // tile overlaps with ROI? + pContext->m_bInROI = ((rLeft >= tRight + rExt || rTop >= tBottom + rExt || tLeft > rRight + rExt || + tTop > rBottom + rExt || pSC->cRow * 16 > rBottom + rExt) ? FALSE : TRUE); + } + } + + if(pSC->m_Dparam->bDecodeFullFrame || pContext->m_bInROI){ + if ((result = DecodeMacroblockDC(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK) + return result; + + if(pSC->m_Dparam->bDecodeLP){ + if ((result = DecodeMacroblockLowpass(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK) + return result; + } + + predDCACDec(pSC); + + dequantizeMacroblock(pSC); + + if(pSC->m_Dparam->bDecodeHP){ + if ((result = DecodeMacroblockHighpass(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK) + return result; + predACDec(pSC); + } + + /* keep necessary info for future prediction */ + updatePredInfo(pSC, &pSC->MBInfo, (Int)pSC->cColumn, pSC->m_param.cfColorFormat); + } + } + + if((!pSC->m_Dparam->bDecodeFullFrame) && + ((pSC->cColumn * 16 > pSC->m_Dparam->cROIRightX + 25) || (pSC->cColumn * 16 + 25 < pSC->m_Dparam->cROILeftX) + || (pSC->cRow * 16 > pSC->m_Dparam->cROIBottomY + 25) || (pSC->cRow * 16 + 25 < pSC->m_Dparam->cROITopY))) + { + // do nothing + } + else { + pSC->Transform(pSC); + } + + if (jend) { + pSC->m_pNextSC->cRow = pSC->cRow; + pSC->m_pNextSC->cColumn = pSC->cColumn; + pSC = pSC->m_pNextSC; + } + } + + return result; +} + +//================================================================ +// Inverse Color Conversion +//#define _ICC1(r, g, b) (g^=b^=g^=b, r^=g^=r^=g, b += ((g) >> 1), r += ((g) >> 1), g -= (b+3*r+2) >> 2) +//#define _ICC(r, g, b) (g^=b^=g^=b, r^=g^=r^=g, b += ((g) >> 1), r += ((g) >> 1), g -= (b+3*r+2) >> 2) +//================================================================ +//#define _ICC1(r, g, b) r -= (g >> 1), g += r, r -= ((b + 1) >> 1), b += r +//#define _ICC(r, g, b) r -= (g >> 1), g += r, r -= (b >> 1), b += r + +#define _ICC(r, g, b) (g -= ((r + 0) >> 1), r -= ((b + 1) >> 1) - g, b += r) +#define _ICC_CMYK(c, m, y, k) (k -= ((m + 1) >> 1), m -= (c >> 1) - k, c -= ((y + 1) >> 1) - m, y += c) + +#define _CLIP2(l, v, h) ((v) < (l) ? (l) : ((h) < (v) ? (h) : (v))) +#define _CLIP8(v) ((U8)_CLIP2(0, v, 255)) +#define _CLIP16(v) ((I16)_CLIP2(-32768, v, 32767)) +#define _CLIPU16(v) ((U16)_CLIP2(0, v, 65535)) + +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +//inverseConvert: Inverse conversion from float RGB to RGBE +static _FORCEINLINE void inverseConvert (PixelI iF, U8 *pRGB, U8 *pE) +{ + if (iF <= 0) { + *pRGB = *pE = 0; + } + else if ((iF >> 7) > 1) { + /** normal form **/ + *pE = (U8) (iF >> 7); //+ 1; + *pRGB = (iF & 0x7f) | 0x80; + } + else { + /** denormal form **/ + *pE = 1; + *pRGB = (U8) iF; + } +} + +#ifdef __ANSI__ +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif // __ANSI__ + +static _FORCEINLINE void inverseConvertRGBE (PixelI iFr, PixelI iFg, PixelI iFb, U8 *pR, U8 *pG, U8 *pB, U8 *pE) +{ + U8 iShift; + + U8 pR_E, pG_E, pB_E; + + inverseConvert (iFr, pR, &pR_E); + inverseConvert (iFg, pG, &pG_E); + inverseConvert (iFb, pB, &pB_E); + + *pE = max(max(pR_E, pG_E), pB_E); + + if(*pE > pR_E){ + iShift = (*pE - pR_E); + *pR = (U8)((((int)*pR) * 2 + 1) >> (iShift + 1)); + } + if(*pE > pG_E){ + iShift = (*pE - pG_E); + *pG = (U8)((((int)*pG) * 2 + 1) >> (iShift + 1)); + } + if(*pE > pB_E){ + iShift = (*pE - pB_E); + *pB = (U8)((((int)*pB) * 2 + 1) >> (iShift + 1)); + } +} + + +//pixel to float 32! +static _FORCEINLINE float pixel2float(PixelI _h, const char _c, const unsigned char _lm) +{ + union uif + { + I32 i; + float f; + } x; + + I32 s, iTempH, m, e, lmshift = (1 << _lm); + + // assert (_c <= 127); + + iTempH = (I32) _h ; + s = (iTempH >> 31); + iTempH = (iTempH ^ s) - s; // abs(iTempH) + + e = (U32) iTempH >> _lm;// & ((1 << (31 - _lm)) - 1); + m = (iTempH & (lmshift - 1)) | lmshift; // actual mantissa, with normalizer + if (e == 0) { // denormal land + m ^= lmshift; // normalizer removed + e = 1; // actual exponent + } + + e += (127 - _c); + while (m < lmshift && e > 1 && m > 0) { // denormal originally, see if normal is possible + e--; + m <<= 1; + } + if (m < lmshift) // truly denormal + e = 0; + else + m ^= lmshift; + m <<= (23 - _lm); + + x.i = (s & 0x80000000) | (e << 23) | m; + + return x.f; +} + +//convert Half-16 to internal format, only need to handle sign bit +static _FORCEINLINE U16 backwardHalf (PixelI hHalf) +{ + PixelI s; + s = hHalf >> 31; + hHalf = ((hHalf & 0x7fff) ^ s) - s; // don't worry about overflow + return (U16) hHalf; +} + + +Void interpolateUV(CWMImageStrCodec * pSC) +{ + const COLORFORMAT cfExt = pSC->WMII.cfColorFormat; + const size_t cWidth = pSC->cmbWidth * 16; + PixelI * pSrcU = pSC->a0MBbuffer[1], * pSrcV = pSC->a0MBbuffer[2]; + PixelI * pDstU = pSC->pResU, * pDstV = pSC->pResV; + size_t iRow, iColumn; + size_t iIdxS = 0, iIdxD = 0; + + if(pSC->m_param.cfColorFormat == YUV_422){ // 422 => 444, interpolate horizontally + for(iRow = 0; iRow < 16; iRow ++){ + for(iColumn = 0; iColumn < cWidth; iColumn += 2){ + iIdxS = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7]; + iIdxD = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + // copy over + pDstU[iIdxD] = pSrcU[iIdxS]; + pDstV[iIdxD] = pSrcV[iIdxS]; + + if(iColumn > 0){ + size_t iL = iColumn - 2, iIdxL = ((iL >> 4) << 8) + idxCC[iRow][iL & 15]; + size_t iC = iColumn - 1, iIdxC = ((iC >> 4) << 8) + idxCC[iRow][iC & 15]; + + // interpolate + pDstU[iIdxC] = ((pDstU[iIdxL] + pDstU[iIdxD] + 1) >> 1); + pDstV[iIdxC] = ((pDstV[iIdxL] + pDstV[iIdxD] + 1) >> 1); + } + } + + //last pixel + iIdxS = (((iColumn - 1) >> 4) << 8) + idxCC[iRow][(iColumn - 1) & 15]; + pDstU[iIdxS] = pDstU[iIdxD]; + pDstV[iIdxS] = pDstV[iIdxD]; + } + } + else{ // 420 => 422 or 444, interpolate vertically + const size_t cShift = (cfExt == YUV_422 ? 3 : 4); + + for(iColumn = 0; iColumn < cWidth; iColumn += 2){ + const size_t cMB = ((iColumn >> 4) << (4 + cShift)), cPix = (iColumn >> (4 - cShift)) & ((1 << cShift) - 1); + + for(iRow = 0; iRow < 16; iRow += 2){ + iIdxS = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7]; + iIdxD = cMB + idxCC[iRow][cPix]; + + // copy over + pDstU[iIdxD] = pSrcU[iIdxS]; + pDstV[iIdxD] = pSrcV[iIdxS]; + + if(iRow > 0){ + size_t iIdxT = cMB + idxCC[iRow - 2][cPix]; + size_t iIdxC = cMB + idxCC[iRow - 1][cPix]; + + // interpolate + pDstU[iIdxC] = ((pDstU[iIdxT] + pDstU[iIdxD] + 1) >> 1); + pDstV[iIdxC] = ((pDstV[iIdxT] + pDstV[iIdxD] + 1) >> 1); + } + } + + //last row + iIdxS = cMB + idxCC[15][cPix]; + if(pSC->cRow == pSC->cmbHeight){ // image boundary + pDstU[iIdxS] = pDstU[iIdxD]; + pDstV[iIdxS] = pDstV[iIdxD]; + } + else{ // need next MB row + size_t iIdxB = ((iColumn >> 4) << 6) + idxCC_420[0][(iColumn >> 1) & 7]; + + pDstU[iIdxS] = ((pSC->a1MBbuffer[1][iIdxB] + pDstU[iIdxD] + 1) >> 1); + pDstV[iIdxS] = ((pSC->a1MBbuffer[2][iIdxB] + pDstV[iIdxD] + 1) >> 1); + } + } + + if(cfExt != YUV_422){ // 420 => 444, interpolate horizontally + for(iRow = 0; iRow < 16; iRow ++){ + for(iColumn = 1; iColumn < cWidth - 2; iColumn += 2){ + size_t iIdxL = (((iColumn - 1) >> 4) << 8) + idxCC[iRow][(iColumn - 1) & 15]; + + iIdxD = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + iIdxS = (((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]; + + pDstU[iIdxD] = ((pDstU[iIdxS] + pDstU[iIdxL] + 1) >> 1); + pDstV[iIdxD] = ((pDstV[iIdxS] + pDstV[iIdxL] + 1) >> 1); + } + + // last pixel + iIdxD = (((cWidth - 1) >> 4) << 8) + idxCC[iRow][(cWidth - 1) & 15]; + pDstU[iIdxD] = pDstU[iIdxS]; + pDstV[iIdxD] = pDstV[iIdxS]; + } + } + } +} + +// write one MB row of Y_ONLY/CF_ALPHA/YUV_444/N_CHANNEL to output buffer +Void outputNChannel(CWMImageStrCodec * pSC, size_t iFirstRow, size_t iFirstColumn, size_t cWidth, size_t cHeight, size_t iShift, PixelI iBias) +{ + const CWMImageInfo* pII = &pSC->WMII; + const size_t cChannel = pII->cfColorFormat == Y_ONLY ? 1 : pSC->WMISCP.cChannel; + // const U8 cbChannels[BDB_MAX] = {-1, 1, 2, 2, 2, 4, 4, -1, -1, }; + const U8 nLen = pSC->WMISCP.nLenMantissaOrShift; + const I8 nExpBias = pSC->WMISCP.nExpBias; + + PixelI * pChannel[16]; + size_t iChannel, iRow, iColumn; + size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16, iY; + + assert(cChannel <= 16); + + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pChannel[iChannel & 15] = pSC->a0MBbuffer[iChannel]; + + if(pSC->m_bUVResolutionChange) + pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV; + + switch(pSC->WMII.bdBitDepth){ + case BD_8: + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + U8 * pDst = (U8 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift); + + pDst[iChannel] = _CLIP8(p); + } + } + } + break; + + case BD_16: + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + U16 * pDst = (U16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift); + + p <<= nLen; + pDst[iChannel] = _CLIPU16(p); + } + } + } + break; + + case BD_16S: + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + I16 * pDst = (I16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift); + + p <<= nLen; + pDst[iChannel] = _CLIP16(p); + } + } + } + break; + + case BD_16F: + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + U16 * pDst = (U16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + iBias) >> iShift); + + pDst[iChannel] = backwardHalf(p); + } + } + } + break; + + case BD_32: + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + U32 * pDst = (U32 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + iBias) >> iShift); + + p <<= nLen; + pDst[iChannel] = (U32)(p); + } + } + } + break; + + case BD_32S: + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + I32 * pDst = (I32 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + iBias) >> iShift); + + p <<= nLen; + pDst[iChannel] = (I32)(p); + } + } + } + break; + + case BD_32F: + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + float * pDst = (float *)pSC->WMIBI.pv + iY + pOffsetX[iColumn]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + iBias) >> iShift); + + pDst[iChannel] = pixel2float (p, nExpBias, nLen); + } + } + } + break; + + default: + assert(0); + break; + } +} + +static void fixup_Y_ONLY_to_Others( + const CWMImageStrCodec* pSC, + const CWMImageBufferInfo* pBI) +{ + const CWMImageInfo* pII = &pSC->WMII; + const CWMIStrCodecParam* pSCP = &pSC->WMISCP; + size_t cWidth = 0, cHeight = 0; + size_t idxY = 0, idxX = 0; + + if (CF_RGB != pII->cfColorFormat || Y_ONLY != pSCP->cfColorFormat) + return; + + cWidth = 0 != pII->cROIWidth ? pII->cROIWidth : pII->cWidth; + cHeight = 0 != pII->cROIHeight ? pII->cROIHeight : pII->cHeight; + +#define fixup(type, nCh) \ +for (idxY = 0; idxY < cHeight; ++idxY) \ +{ \ + type * pT = (type *)((U8*)pBI->pv + pBI->cbStride * idxY); \ + for (idxX = 0; idxX < cWidth; ++idxX) \ + { \ + pT[2] = pT[1] = pT[0]; \ + pT += nCh; \ + } \ +} \ +break + + switch (pII->bdBitDepth) + { + case BD_8: + fixup(U8, (pII->cBitsPerUnit >> 3)); + break; + + case BD_16: + case BD_16S: + case BD_16F: + fixup(U16, (pII->cBitsPerUnit >> 3) / sizeof(U16)); + break; + + case BD_32: + case BD_32S: + case BD_32F: + fixup(U32, (pII->cBitsPerUnit >> 3) / sizeof(float)); + break; + + case BD_5: + case BD_10: + case BD_565: + default: + break; + } +} + +// centralized alpha channel color conversion, small perf penalty +Int outputMBRowAlpha(CWMImageStrCodec * pSC) +{ + if(pSC->WMII.bdBitDepth == BD_8 && pSC->WMISCP.cfColorFormat == CF_RGB) // has been taken care of and optimized out + return ICERR_OK; + + if(pSC->m_bSecondary == FALSE && pSC->m_pNextSC != NULL){ // with alpha channel + const BITDEPTH_BITS bd = pSC->WMII.bdBitDepth; + const PixelI iShift = (pSC->m_param.bScaledArith ? SHIFTZERO + QPFRACBITS : 0); + const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16); + const size_t cWidth = (pSC->m_Dparam->cROIRightX + 1); + const size_t iFirstRow = ((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)), iFirstColumn = pSC->m_Dparam->cROILeftX; + const size_t iAlphaPos = pSC->WMII.cLeadingPadding + (pSC->WMII.cfColorFormat == CMYK ? 4 : 3);//only RGB and CMYK may have interleaved alpha + const PixelI * pA = pSC->m_pNextSC->a0MBbuffer[0]; + const U8 nLen = pSC->WMISCP.nLenMantissaOrShift; + const I8 nExpBias = pSC->WMISCP.nExpBias; + size_t iRow, iColumn; + size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16, iY; + + if (CF_RGB != pSC->WMII.cfColorFormat && CMYK != pSC->WMII.cfColorFormat) + return ICERR_ERROR; + + if(bd == BD_8){ + const PixelI iBias = (1 << (iShift + 7)) + (iShift == 0 ? 0 : (1 << (iShift - 1))); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + PixelI a = ((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift); + ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = _CLIP8(a); + } + } + else if(bd == BD_16){ + const PixelI iBias = (1 << (iShift + 15)) + (iShift == 0 ? 0 : (1 << (iShift - 1))); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + PixelI a = (((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen); + ((U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = _CLIPU16(a); + } + } + else if(bd == BD_16S){ + const PixelI iBias = (iShift == 0 ? 0 : (1 << (iShift - 1))); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + PixelI a = (((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen); + ((I16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = _CLIP16(a); + } + } + else if(bd == BD_16F){ + const PixelI iBias = (iShift == 0 ? 0 : (1 << (iShift - 1))); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + PixelI a = ((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift); + ((U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = backwardHalf(a); + } + } + else if(bd == BD_32S){ + const PixelI iBias = (iShift == 0 ? 0 : (1 << (iShift - 1))); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + PixelI a = (((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen); + ((I32 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = a; + } + } + else if(bd == BD_32F){ + const PixelI iBias = (iShift == 0 ? 0 : (1 << (iShift - 1))); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + PixelI a = ((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift); + ((float *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = pixel2float (a, nExpBias, nLen); + } + } + else // not supported + return ICERR_ERROR; + } + + return ICERR_OK; +} + +Int outputMBRow(CWMImageStrCodec * pSC) +{ + const COLORFORMAT cfExt = (pSC->m_param.cfColorFormat == Y_ONLY ? Y_ONLY : pSC->WMII.cfColorFormat); + const BITDEPTH_BITS bd = pSC->WMII.bdBitDepth; + const PixelI iShift = (pSC->m_param.bScaledArith ? SHIFTZERO + QPFRACBITS : 0); + const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16); + const size_t cWidth = (pSC->m_Dparam->cROIRightX + 1); + const size_t iFirstRow = ((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)), iFirstColumn = pSC->m_Dparam->cROILeftX; + const PixelI *pY = pSC->a0MBbuffer[0]; + const PixelI *pU = (pSC->m_bUVResolutionChange ? pSC->pResU : pSC->a0MBbuffer[1]); + const PixelI *pV = (pSC->m_bUVResolutionChange ? pSC->pResV : pSC->a0MBbuffer[2]); + const PixelI *pA = NULL; + const size_t iB = (pSC->WMII.bRGB ? 2 : 0); + const size_t iR = 2 - iB; + const U8 nLen = pSC->WMISCP.nLenMantissaOrShift; + const I8 nExpBias = pSC->WMISCP.nExpBias; + size_t iRow, iColumn, iIdx; + size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * (cfExt == YUV_420 ? 8 : 16), iY; + + + if (pSC->m_pNextSC) { + assert (pSC->m_param.bScaledArith == pSC->m_pNextSC->m_param.bScaledArith); // will be relaxed later + } + + // guard output buffer + if(checkImageBuffer(pSC, pSC->WMII.oOrientation >= O_RCW ? pSC->WMII.cROIHeight : pSC->WMII.cROIWidth, cHeight - iFirstRow) != ICERR_OK) + return ICERR_ERROR; + + if(pSC->m_bUVResolutionChange) + interpolateUV(pSC); + + if(pSC->WMISCP.bYUVData){ + I32 * pDst = (I32 *)pSC->WMIBI.pv + (pSC->cRow - 1) * + (pSC->m_param.cfColorFormat == YUV_420 ? 8 : 16) * pSC->WMIBI.cbStride / sizeof(I32); + + switch(pSC->m_param.cfColorFormat){ + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + PixelI * pChannel[16]; + size_t iChannel; + + const size_t cChannel = pSC->WMII.cfColorFormat == Y_ONLY ? 1 : pSC->WMISCP.cChannel; + assert(cChannel <= 16); + + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pChannel[iChannel & 15] = pSC->a0MBbuffer[iChannel]; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + I32 * pRow = pDst; + for(iColumn = iFirstColumn; iColumn < cWidth; iColumn ++){ + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]]; + + *pRow++ = p; + } + } + pDst += pSC->WMIBI.cbStride / sizeof(I32); + } + } + break; + + case YUV_422: + { + PixelI y0, y1, u, v; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + I32 * pRow = pDst; + for(iColumn = iFirstColumn; iColumn < cWidth; iColumn += 2){ + iIdx = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7]; + u = pU[iIdx], v = pV[iIdx]; + + y0 = pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]]; + y1 = pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]]; + + pRow[0] = u, pRow[1] = y0, pRow[2] = v, pRow[3] = y1; + pRow += 4; + } + pDst += pSC->WMIBI.cbStride / sizeof(I32); + } + } + break; + + case YUV_420: + { + PixelI y0, y1, y2, y3, u, v; + // const size_t iS4[8][4] = {{0, 1, 2, 3}, {2, 3, 0, 1}, {1, 0, 3, 2}, {3, 2, 1, 0}, {1, 3, 0, 2}, {3, 1, 2, 0}, {0, 2, 1, 3}, {2, 0, 3, 1}}; + + for(iRow = iFirstRow; iRow < cHeight; iRow += 2){ + I32 * pRow = pDst; + for(iColumn = iFirstColumn; iColumn < cWidth; iColumn += 2){ + iIdx = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7]; + u = pU[iIdx], v = pV[iIdx]; + + y0 = pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]]; + y1 = pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]]; + y2 = pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]]; + y3 = pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]]; + + pRow[0] = y0, pRow[1] = y1, pRow[2] = y2, pRow[3] = y3, pRow[4] = u, pRow[5] = v; + pRow += 6; + } + pDst += pSC->WMIBI.cbStride / sizeof(I32); + } + } + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_8){ + U8 * pDst; + const PixelI iBias1 = 128 << iShift; + const PixelI iBias2 = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0; + const PixelI iBias = iBias1 + iBias2; + + switch(cfExt){ + case CF_RGB: + { + PixelI r, g, b, a; + + if (pSC->m_pNextSC && pSC->WMISCP.uAlphaMode > 0) { // RGBA + + pA = pSC->m_pNextSC->a0MBbuffer[0]; + + if (pSC->m_param.bScaledArith == FALSE) { + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + a = pA[iIdx] + iBias; + + _ICC(r, g, b); + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if ((g | b | r | a) & ~0xff) + pDst[iR] = _CLIP8(r), pDst[1] = _CLIP8(g), pDst[iB] = _CLIP8(b), pDst[3] = _CLIP8(a); + else + pDst[iR] = (U8)r, pDst[1] = (U8)g, pDst[iB] = (U8)b, pDst[3] = (U8)(a); + } + } + else{ + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + a = pA[iIdx] + iBias; + + _ICC(r, g, b); + + g >>= iShift, b >>= iShift, r >>= iShift, a >>= iShift; + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if ((g | b | r | a) & ~0xff) + pDst[iR] = _CLIP8(r), pDst[1] = _CLIP8(g), pDst[iB] = _CLIP8(b), pDst[3] = _CLIP8(a); + else + pDst[iR] = (U8)r, pDst[1] = (U8)g, pDst[iB] = (U8)b, pDst[3] = (U8)(a); + } + } + } + else { + if (pSC->m_param.bScaledArith == FALSE) { + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if ((g | b | r) & ~0xff) + pDst[iR] = _CLIP8(r), pDst[1] = _CLIP8(g), pDst[iB] = _CLIP8(b); + else + pDst[iR] = (U8)r, pDst[1] = (U8)g, pDst[iB] = (U8)b; + } + } + else{ + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + g >>= iShift, b >>= iShift, r >>= iShift; + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if ((g | b | r) & ~0xff) + pDst[iR] = _CLIP8(r), pDst[1] = _CLIP8(g), pDst[iB] = _CLIP8(b); + else + pDst[iR] = (U8)r, pDst[1] = (U8)g, pDst[iB] = (U8)b; + } + } + } + break; + } + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias); + break; + + case YUV_422: + { + PixelI y0, y1, u, v; + // const ORIENTATION oO = pSC->WMII.oOrientation; + // const size_t i0 = ((oO > O_FLIPV && oO <= O_RCW_FLIPVH) ? 1 : 0), i1 = 1 - i0; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn += 2){ + iIdx = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7]; + u = ((pU[iIdx] + iBias) >> iShift), v = ((pV[iIdx] + iBias) >> iShift); + + y0 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift); + y1 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] + iBias) >> iShift); + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> 1] + iY; + if ((y0 | y1 | u | v) & ~0xff)//UYVY + pDst[0] = _CLIP8(u), pDst[1] = _CLIP8(y0), pDst[2] = _CLIP8(v), pDst[3] = _CLIP8(y1); + else + pDst[0] = (U8)u, pDst[1] = (U8)y0, pDst[2] = (U8)v, pDst[3] = (U8)y1; + } + } + } + break; + + case YUV_420: + { + PixelI y0, y1, y2, y3, u, v; + const size_t iS4[8][4] = {{0, 1, 2, 3}, {2, 3, 0, 1}, {1, 0, 3, 2}, {3, 2, 1, 0}, {1, 3, 0, 2}, {3, 1, 2, 0}, {0, 2, 1, 3}, {2, 0, 3, 1}}; + const ORIENTATION oO = pSC->WMII.oOrientation; + const size_t i0 = iS4[oO][0], i1 = iS4[oO][1], i2 = iS4[oO][2], i3 = iS4[oO][3]; + + for(iRow = iFirstRow; iRow < cHeight; iRow += 2){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> 1]; iColumn < cWidth; iColumn += 2){ + iIdx = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7]; + u = ((pU[iIdx] + iBias) >> iShift), v = ((pV[iIdx] + iBias) >> iShift); + + y0 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift); + y1 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] + iBias) >> iShift); + y2 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] + iBias) >> iShift); + y3 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] + iBias) >> iShift); + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> 1] + iY; + if ((y0 | y1 | y2 | y3 | u | v) & ~0xff) + pDst[i0] = _CLIP8(y0), pDst[i1] = _CLIP8(y1), pDst[i2] = _CLIP8(y2), pDst[i3] = _CLIP8(y3), pDst[4] = _CLIP8(u), pDst[5] = _CLIP8(v); + else + pDst[i0] = (U8)y0, pDst[i1] = (U8)y1, pDst[i2] = (U8)y2, pDst[i3] = (U8)y3, pDst[4] = (U8)u, pDst[5] = (U8)v; + } + } + } + break; + + case CMYK: + { + PixelI c, m, y, k; + PixelI * pK = pSC->a0MBbuffer[3]; + + for(iRow = iFirstRow; iRow < cHeight; iRow++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + m = -pY[iIdx] + iBias1, c = pU[iIdx], y = -pV[iIdx], k = pK[iIdx] + iBias2; + + _ICC_CMYK(c, m, y, k); // color conversion + + c >>= iShift, m >>= iShift, y >>= iShift, k >>= iShift; + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if ((c | m | y | k) & ~0xff) + pDst[0] = _CLIP8(c), pDst[1] = _CLIP8(m), pDst[2] = _CLIP8(y), pDst[3] = _CLIP8(k); + else + pDst[0] = (U8)c, pDst[1] = (U8)m, pDst[2] = (U8)y, pDst[3] = (U8)k; + } + } + } + break; + + case CF_RGBE: + { + PixelI r, g, b; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias2, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + + inverseConvertRGBE (r >> iShift, g >> iShift, b >> iShift, pDst, pDst + 1, pDst + 2, pDst + 3); + } + } + } + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_16){ + const PixelI iBias = (((1 << 15) >> nLen) << iShift) + (iShift == 0 ? 0 : (1 << (iShift - 1))); + U16 * pDst; + + switch(cfExt){ + case CF_RGB: + { + PixelI r, g, b; + if (pSC->m_param.bScaledArith == FALSE) { + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + g <<= nLen, b <<= nLen, r <<= nLen; + + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + + if ((g | b | r) & ~0xffff) + pDst[0] = _CLIPU16(r), pDst[1] = _CLIPU16(g), pDst[2] = _CLIPU16(b); + else + pDst[0] = (U16)r, pDst[1] = (U16)g, pDst[2] = (U16)b; + } + } + else{ + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + g = (g >> iShift) << nLen, b = (b >> iShift) << nLen, r = (r >> iShift) << nLen; + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if ((g | b | r) & ~0xffff) + pDst[0] = _CLIPU16(r), pDst[1] = _CLIPU16(g), pDst[2] = _CLIPU16(b); + else + pDst[0] = (U16)r, pDst[1] = (U16)g, pDst[2] = (U16)b; + } + } + break; + } + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias); + break; + + case YUV_422: + { + PixelI y0, y1, u, v; + const ORIENTATION oO = pSC->WMII.oOrientation; + const size_t i0 = ((oO == O_FLIPH || oO == O_FLIPVH || oO == O_RCW_FLIPV || oO == O_RCW_FLIPVH) ? 1 : 0), i1 = 1 - i0; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn += 2){ + iIdx = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7]; + u = ((pU[iIdx] + iBias) >> iShift) << nLen, v = ((pV[iIdx] + iBias) >> iShift) << nLen; + + y0 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen; + y1 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] + iBias) >> iShift) << nLen; + + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> 1] + iY; + if ((y0 | y1 | u | v) & ~0xffff) + { + pDst[i0] = _CLIPU16(u); + pDst[i1] = _CLIPU16(y0); + pDst[2] = _CLIPU16(v); + pDst[3] = _CLIPU16(y1); + } + else + { + pDst[i0] = (U16)(u); + pDst[i1] = (U16)(y0); + pDst[2] = (U16)(v); + pDst[3] = (U16)(y1); + } + } + } + } + break; + + case YUV_420: + { + PixelI y0, y1, y2, y3, u, v; + const size_t iS4[8][4] = {{0, 1, 2, 3}, {2, 3, 0, 1}, {1, 0, 3, 2}, {3, 2, 1, 0}, {1, 3, 0, 2}, {3, 1, 2, 0}, {0, 2, 1, 3}, {2, 0, 3, 1}}; + const ORIENTATION oO = pSC->WMII.oOrientation; + const size_t i0 = iS4[oO][0], i1 = iS4[oO][1], i2 = iS4[oO][2], i3 = iS4[oO][3]; + + for(iRow = iFirstRow; iRow < cHeight; iRow += 2){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> 1]; iColumn < cWidth; iColumn += 2){ + iIdx = ((iColumn >> 3) << 6) + idxCC[iRow][(iColumn >> 1) & 7]; + u = ((pU[iIdx] + iBias) >> iShift) << nLen, v = ((pV[iIdx] + iBias) >> iShift) << nLen; + + y0 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen; + y1 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] + iBias) >> iShift) << nLen; + y2 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] + iBias) >> iShift) << nLen; + y3 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] + iBias) >> iShift) << nLen; + + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> 1] + iY; + if ((y0 | y1 | y2 | y3 | u | v) & ~0xffff) + { + pDst[i0] = _CLIPU16(y0); + pDst[i1] = _CLIPU16(y1); + pDst[i2] = _CLIPU16(y2); + pDst[i3] = _CLIPU16(y3); + pDst[4] = _CLIPU16(u); + pDst[5] = _CLIPU16(v); + } + else + { + pDst[i0] = (U16)(y0); + pDst[i1] = (U16)(y1); + pDst[i2] = (U16)(y2); + pDst[i3] = (U16)(y3); + pDst[4] = (U16)(u); + pDst[5] = (U16)(v); + } + } + } + } + break; + + case CMYK: + { + PixelI c, m, y, k; + PixelI * pK = pSC->a0MBbuffer[3]; + const PixelI iBias1 = (32768 >> nLen) << iShift; + const PixelI iBias2 = iBias - iBias1; + + for(iRow = iFirstRow; iRow < cHeight; iRow++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + m = -pY[iIdx] + iBias1, c = pU[iIdx], y = -pV[iIdx], k = pK[iIdx] + iBias2; + + _ICC_CMYK(c, m, y, k); // color conversion + + c = (c >> iShift) << nLen, m = (m >> iShift) << nLen, y = (y >> iShift) << nLen, k = (k >> iShift) << nLen; + + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if ((c | m | y | k) & ~0xffff) + pDst[0] = _CLIPU16(c), pDst[1] = _CLIPU16(m), pDst[2] = _CLIPU16(y), pDst[3] = _CLIPU16(k); + else + pDst[0] = (U16)(c), pDst[1] = (U16)(m), pDst[2] = (U16)(y), pDst[3] = (U16)(k); + } + } + } + break; + default: + assert(0); + break; + } + } + else if(bd == BD_16S){ + const PixelI iBias = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0; + I16 * pDst; + + switch(cfExt){ + case CF_RGB: + { + PixelI r, g, b; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + r = (r >> iShift) << nLen, g = (g >> iShift) << nLen, b = (b >> iShift) << nLen; + + pDst = (I16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + pDst[0] = _CLIP16(r), pDst[1] = _CLIP16(g), pDst[2] = _CLIP16(b); + } + break; + } + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias); + break; + + case CMYK: + { + PixelI c, m, y, k; + PixelI * pK = pSC->a0MBbuffer[3]; + + for(iRow = iFirstRow; iRow < cHeight; iRow++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + m = -pY[iIdx], c = pU[iIdx], y = -pV[iIdx], k = pK[iIdx] + iBias; + + _ICC_CMYK(c, m, y, k); // color conversion + + c = (c >> iShift) << nLen, m = (m >> iShift) << nLen, y = (y >> iShift) << nLen, k = (k >> iShift) << nLen; + + pDst = (I16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + pDst[0] = (I16)(c), pDst[1] = (I16)(m), pDst[2] = (I16)(y), pDst[3] = (I16)(k); + } + } + } + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_16F){ + const PixelI iBias = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0; + U16 *pDst; + + switch (cfExt) + { + case CF_RGB: + { + PixelI r, g, b; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + pDst[0] = backwardHalf(r >> iShift); + pDst[1] = backwardHalf(g >> iShift); + pDst[2] = backwardHalf(b >> iShift); + } + } + break; + } + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias); + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_32){ + const PixelI iBias = (((1 << 31) >> nLen) << iShift) + (iShift == 0 ? 0 : (1 << (iShift - 1))); + U32 * pDst; + + switch (cfExt) + { + case CF_RGB: + { + PixelI r, g, b; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + pDst = (U32 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + pDst[0] = ((r >> iShift) << nLen); + pDst[1] = ((g >> iShift) << nLen); + pDst[2] = ((b >> iShift) << nLen); + } + } + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias); + break; + } + default: + assert(0); + break; + } + } + else if(bd == BD_32S){ + const PixelI iBias = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0; + int * pDst; + + switch (cfExt) + { + case CF_RGB: + { + PixelI r, g, b; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + pDst = (int *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + pDst[0] = ((r >> iShift) << nLen); + pDst[1] = ((g >> iShift) << nLen); + pDst[2] = ((b >> iShift) << nLen); + } + } + break; + } + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias); + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_32F){ + const PixelI iBias = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0; + float * pDst; + + switch (cfExt) + { + case CF_RGB: + { + PixelI r, g, b; + + for(iRow = iFirstRow; iRow < cHeight; iRow ++){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + pDst = (float *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + pDst[0] = pixel2float (r >> iShift, nExpBias, nLen); + pDst[1] = pixel2float (g >> iShift, nExpBias, nLen); + pDst[2] = pixel2float (b >> iShift, nExpBias, nLen); + } + } + break; + } + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias); + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_5){ + const PixelI iBias = (16 << iShift) + (pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0); + PixelI r, g, b; + U16 * pDst; + + assert(cfExt == CF_RGB); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + g >>= iShift, b >>= iShift, r >>= iShift; + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if (pSC->m_param.bRBSwapped) + pDst[0] = (U16)_CLIP2(0, b, 31) + (((U16)_CLIP2(0, g, 31)) << 5) + (((U16)_CLIP2(0, r, 31)) << 10); + else + pDst[0] = (U16)_CLIP2(0, r, 31) + (((U16)_CLIP2(0, g, 31)) << 5) + (((U16)_CLIP2(0, b, 31)) << 10); + } + } + else if(bd == BD_565){ + const PixelI iBias = (32 << iShift) + (pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0); + PixelI r, g, b; + U16 * pDst; + + assert(cfExt == CF_RGB); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + g >>= iShift, b >>= iShift + 1, r >>= iShift + 1; + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if (pSC->m_param.bRBSwapped) + pDst[0] = (U16)_CLIP2(0, b, 31) + (((U16)_CLIP2(0, g, 63)) << 5) + (((U16)_CLIP2(0, r, 31)) << 11); + else + pDst[0] = (U16)_CLIP2(0, r, 31) + (((U16)_CLIP2(0, g, 63)) << 5) + (((U16)_CLIP2(0, b, 31)) << 11); + } + } + else if(bd == BD_10){ + const PixelI iBias = (512 << iShift) + (pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0); + PixelI r, g, b; + U32 * pDst; + + assert(cfExt == CF_RGB); + + for(iRow = iFirstRow; iRow < cHeight; iRow ++) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){ + iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx]; + + _ICC(r, g, b); + + g >>= iShift, b >>= iShift, r >>= iShift; + + pDst = (U32 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY; + if (pSC->m_param.bRBSwapped) + pDst[0] = (U32)_CLIP2(0, b, 1023) + + (((U32)_CLIP2(0, g, 1023)) << 10) + + (((U32)_CLIP2(0, r, 1023)) << 20); + else + pDst[0] = (U32)_CLIP2(0, r, 1023) + + (((U32)_CLIP2(0, g, 1023)) << 10) + + (((U32)_CLIP2(0, b, 1023)) << 20); + } + } + else if(bd == BD_1){ + const size_t iPos = pSC->WMII.cLeadingPadding; + const Int iTh = (iShift > 0) ? (1 << (iShift - 1)) : 1; + assert(cfExt == Y_ONLY && pSC->m_param.cfColorFormat == Y_ONLY); + + if(pSC->WMII.oOrientation < O_RCW) + for(iRow = iFirstRow; iRow < cHeight; iRow ++) { + iY = pOffsetY[iRow] + iPos; + for(iColumn = iFirstColumn; iColumn < cWidth; iColumn ++) { + U8 cByte = ((U8 *)pSC->WMIBI.pv + (pOffsetX[iColumn] >> 3) + iY)[0]; + U8 cShift = (U8)(7 - (pOffsetX[iColumn] & 7)); + ((U8 *)pSC->WMIBI.pv + (pOffsetX[iColumn] >> 3) + iY)[0] ^= // exor is used because we can't assume the byte was originally zero + (((pSC->WMISCP.bBlackWhite + (pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] >= iTh) + + (cByte >> cShift)) & 0x1) << cShift); + } + } + else + for(iRow = iFirstRow; iRow < cHeight; iRow ++) { + iY = pOffsetY[iRow] + iPos; + for(iColumn = iFirstColumn; iColumn < cWidth; iColumn ++) { + U8 cByte = ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + (iY >> 3))[0]; + U8 cShift = (U8)(7 - (iY & 7)); // should be optimized out + ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + (iY >> 3))[0] ^= // exor is used because we can't assume the byte was originally zero + (((pSC->WMISCP.bBlackWhite + (pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] >= iTh) + + (cByte >> cShift)) & 0x1) << cShift); + } + } + } + + if(pSC->WMISCP.uAlphaMode > 0) + if(outputMBRowAlpha(pSC) != ICERR_OK) + return ICERR_ERROR; + +#ifdef REENTRANT_MODE + pSC->WMIBI.cLinesDecoded = cHeight - iFirstRow; + + if (CF_RGB == pSC->WMII.cfColorFormat && Y_ONLY == pSC->WMISCP.cfColorFormat) + { + const CWMImageInfo* pII = &pSC->WMII; + +#define fixupFullSize(type, nCh) \ +for(iRow = iFirstRow; iRow < cHeight; iRow ++) {\ + size_t iOffsetY;\ + for(iColumn = iFirstColumn, iOffsetY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){\ + type *pT = (type*)(U8 *)pSC->WMIBI.pv + iOffsetY + pOffsetX[iColumn];\ + pT[2] = pT[1] = pT[0]; \ + pT += nCh; \ + } \ +} \ +break + + switch (pII->bdBitDepth) + { + case BD_8: + fixupFullSize(U8, (pII->cBitsPerUnit >> 3)); + break; + + case BD_16: + case BD_16S: + case BD_16F: + fixupFullSize(U16, (pII->cBitsPerUnit >> 3) / sizeof(U16)); + break; + + case BD_32: + case BD_32S: + case BD_32F: + fixupFullSize(U32, (pII->cBitsPerUnit >> 3) / sizeof(float)); + break; + + case BD_5: + case BD_10: + case BD_565: + default: + break; + } + } +#endif + + return ICERR_OK; +} + +// Y_ONLY/CF_ALPHA/YUV_444/N_CHANNEL thumbnail decode +Void outputNChannelThumbnail(CWMImageStrCodec * pSC, const PixelI cMul, const size_t rShiftY, size_t iFirstRow, size_t iFirstColumn) +{ + const size_t tScale = pSC->m_Dparam->cThumbnailScale; + const size_t cWidth = (pSC->m_Dparam->cROIRightX + 1); + const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16); + const size_t cChannel = pSC->WMISCP.cChannel; + const U8 nLen = pSC->WMISCP.nLenMantissaOrShift; + const I8 nExpBias = pSC->WMISCP.nExpBias; + size_t nBits = 0; + PixelI iOffset; + PixelI * pChannel[16]; + size_t iChannel, iRow, iColumn; + size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16 / tScale, iY; + + while((size_t)(1U << nBits) < tScale) + nBits ++; + + assert(cChannel <= 16); + + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pChannel[iChannel & 15] = pSC->a0MBbuffer[iChannel]; + + if(pSC->m_bUVResolutionChange) + pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV; + + switch(pSC->WMII.bdBitDepth){ + case BD_8: + for(iOffset = (128 << rShiftY) / cMul, iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + U8 * pDst = (U8 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iOffset) * cMul) >> rShiftY; + + pDst[iChannel] = _CLIP8(p); + } + } + } + break; + + case BD_16: + for(iOffset = (32768 << rShiftY) / cMul, iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + U16 * pDst = (U16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = (((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iOffset) * cMul) >> rShiftY) << nLen; + + pDst[iChannel] = _CLIPU16(p); + } + } + } + break; + + case BD_16S: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + I16 * pDst = (I16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] * cMul) >> rShiftY) << nLen; + + pDst[iChannel] = _CLIP16(p); + } + } + } + break; + + case BD_16F: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + U16 * pDst = (U16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = (pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] * cMul) >> rShiftY; + + pDst[iChannel] = backwardHalf(p); + } + } + } + break; + case BD_32: + for(iOffset = (((1 << 31) >> nLen) << rShiftY) / cMul, iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + U32 * pDst = (U32 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = (((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iOffset) * cMul) >> rShiftY) << nLen; + + pDst[iChannel] = (U32)(p); + } + } + } + break; + case BD_32S: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + I32 * pDst = (I32 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] * cMul) >> rShiftY) << nLen; + + pDst[iChannel] = (I32)(p); + } + } + } + break; + case BD_32F: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + float * pDst = (float *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits]; + + for(iChannel = 0; iChannel < cChannel; iChannel ++){ + PixelI p = (pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] * cMul) >> rShiftY; + + pDst[iChannel] = pixel2float (p, nExpBias, nLen); + } + } + } + break; + + default: + assert(0); + break; + } +} + +// centralized alpha channel thumbnail, small perf penalty +Int decodeThumbnailAlpha(CWMImageStrCodec * pSC, const size_t nBits, const PixelI cMul, const size_t rShiftY) +{ + if(pSC->m_bSecondary == FALSE && pSC->m_pNextSC != NULL){ // with alpha channel + const size_t tScale = (size_t)(1U << nBits); + const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16); + const size_t cWidth = (pSC->m_Dparam->cROIRightX + 1); + const size_t iFirstRow = ((((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)) + tScale - 1) / tScale * tScale); + const size_t iFirstColumn = (pSC->m_Dparam->cROILeftX + tScale - 1) / tScale * tScale; + const size_t iAlphaPos = pSC->WMII.cLeadingPadding + (pSC->WMII.cfColorFormat == CMYK ? 4 : 3);//only RGB and CMYK may have interleaved alpha + const BITDEPTH_BITS bd = pSC->WMII.bdBitDepth; + const PixelI * pSrc = pSC->m_pNextSC->a0MBbuffer[0]; + const U8 nLen = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift; + const I8 nExpBias = pSC->m_pNextSC->WMISCP.nExpBias; + size_t iRow, iColumn; + size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16 / tScale, iY; + + if (CF_RGB != pSC->WMII.cfColorFormat && CMYK != pSC->WMII.cfColorFormat) + return ICERR_ERROR; + + if(bd == BD_8){ + const PixelI offset = (128 << rShiftY) / cMul; + + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + PixelI a = ((pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + offset) * cMul) >> rShiftY; + + ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = _CLIP8(a); + } + } + else if(bd == BD_16){ + const PixelI offset = (32768 << rShiftY) / cMul; + + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + PixelI a = (((pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + offset) * cMul) >> rShiftY) << nLen; + + ((U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = _CLIPU16(a); + } + } + else if(bd == BD_16S){ + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + PixelI a = ((pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] * cMul) >> rShiftY) << nLen; + + ((I16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = _CLIP16(a); + } + } + else if(bd == BD_16F){ + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + PixelI a = (pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] * cMul) >> rShiftY; + + ((U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = backwardHalf(a); + } + } + else if(bd == BD_32S){ + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + PixelI a = ((pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] * cMul) >> rShiftY) << nLen; + + ((I32 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = a; + } + } + else if(bd == BD_32F){ + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + PixelI a = (pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] * cMul) >> rShiftY; + + ((float *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = pixel2float (a, nExpBias, nLen); + } + } + else // not supported + return ICERR_ERROR; + } + + return ICERR_OK; +} + +Int decodeThumbnail(CWMImageStrCodec * pSC) +{ + const size_t tScale = pSC->m_Dparam->cThumbnailScale; + const size_t cHeight = min((pSC->m_Dparam->bDecodeFullFrame ? pSC->WMII.cHeight : pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16); + const size_t cWidth = (pSC->m_Dparam->bDecodeFullFrame ? pSC->WMII.cWidth : pSC->m_Dparam->cROIRightX + 1); + const size_t iFirstRow = ((((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)) + tScale - 1) / tScale * tScale); + const size_t iFirstColumn = (pSC->m_Dparam->cROILeftX + tScale - 1) / tScale * tScale; + const COLORFORMAT cfInt = pSC->m_param.cfColorFormat; + const COLORFORMAT cfExt = (pSC->m_param.cfColorFormat == Y_ONLY ? Y_ONLY : pSC->WMII.cfColorFormat); + const BITDEPTH_BITS bd = pSC->WMII.bdBitDepth; + const OVERLAP ol = pSC->WMISCP.olOverlap; + const size_t iB = (pSC->WMII.bRGB ? 2 : 0); + const size_t iR = 2 - iB; + + const U8 nLen = pSC->WMISCP.nLenMantissaOrShift; + const I8 nExpBias = pSC->WMISCP.nExpBias; + PixelI offset; + size_t iRow, iColumn, iIdx1, iIdx2, iIdx3 = 0, nBits = 0; + PixelI * pSrcY = pSC->a0MBbuffer[0]; + PixelI * pSrcU = pSC->a0MBbuffer[1], * pSrcV = pSC->a0MBbuffer[2]; + size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16 / tScale, iY; + const PixelI cMul = (tScale >= 16 ? (ol == OL_NONE ? 16 : (ol == OL_ONE ? 23 : 34)) : (tScale >= 4 ? (ol == OL_NONE ? 64 : 93) : 258)); + const size_t rShiftY = 8 + (pSC->m_param.bScaledArith ? (SHIFTZERO + QPFRACBITS) : 0); + const size_t rShiftUV = rShiftY - ((pSC->m_param.bScaledArith && tScale >= 16) ? ((cfInt == YUV_420 || cfInt == YUV_422) ? 2 : 1) : 0); + + while((size_t)(1U << nBits) < tScale) + nBits ++; + + assert(tScale == (size_t)(1U << nBits)); + + // guard output buffer + if(checkImageBuffer(pSC, pSC->WMII.oOrientation < O_RCW ? pSC->WMII.cROIWidth : pSC->WMII.cROIHeight, (cHeight - iFirstRow) / pSC->m_Dparam->cThumbnailScale) != ICERR_OK) + return ICERR_ERROR; + + if((((pSC->cRow - 1) * 16) % tScale) != 0) + return ICERR_OK; + + if(pSC->cRow * 16 <= pSC->m_Dparam->cROITopY || pSC->cRow * 16 > pSC->m_Dparam->cROIBottomY + 16) + return ICERR_OK; + + if((cfInt == YUV_422 || cfInt == YUV_420) && cfExt != Y_ONLY){ + PixelI * pDstU = pSC->pResU, * pDstV = pSC->pResV; + + for(iRow = 0; iRow < 16; iRow += tScale){ + for(iColumn = 0; iColumn < cWidth; iColumn += tScale){ + iIdx1 = (cfInt == YUV_422 ? ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7] : ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7]); + iIdx2 = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + + // copy over + pDstU[iIdx2] = pSrcU[iIdx1]; + pDstV[iIdx2] = pSrcV[iIdx1]; + } + } + + if(tScale == 4){ + if(cfInt == YUV_420){ + for(iColumn = 0; iColumn < cWidth; iColumn += 8){ + iIdx1 = ((iColumn >> 4) << 8) + idxCC[0][iColumn & 15]; + iIdx2 = ((iColumn >> 4) << 8) + idxCC[4][iColumn & 15]; + iIdx3 = ((iColumn >> 4) << 8) + idxCC[8][iColumn & 15]; + + pDstU[iIdx2] = ((pDstU[iIdx1] + pDstU[iIdx3] + 1) >> 1); + pDstV[iIdx2] = ((pDstV[iIdx1] + pDstV[iIdx3] + 1) >> 1); + + iIdx1 = ((iColumn >> 4) << 8) + idxCC[12][iColumn & 15]; + pDstU[iIdx1] = pDstU[iIdx3]; + pDstV[iIdx1] = pDstV[iIdx3]; + } + } + + for(iRow = 0; iRow < 16; iRow += 4){ + for(iColumn = 0; iColumn < cWidth - 8; iColumn += 8){ + iIdx1 = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]; + iIdx2 = ((iColumn >> 4) << 8) + idxCC[iRow][(iColumn + 4) & 15]; + iIdx3 = ((iColumn >> 4) << 8) + idxCC[iRow][(iColumn + 8) & 15]; + + pDstU[iIdx2] = ((pDstU[iIdx1] + pDstU[iIdx3] + 1) >> 1); + pDstV[iIdx2] = ((pDstV[iIdx1] + pDstV[iIdx3] + 1) >> 1); + } + + iIdx2 = ((iColumn >> 4) << 8) + idxCC[iRow][(iColumn + 4) & 15]; + pDstU[iIdx2] = pDstU[iIdx3]; + pDstV[iIdx2] = pDstV[iIdx3]; + } + } + + pSrcU = pDstU, pSrcV = pDstV; + } + + if(bd == BD_8){ + U8 * pDst; + + offset = (128 << rShiftY) / cMul; + + switch(cfExt){ + case CF_RGB: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + pDst[iB] = _CLIP8(b), pDst[1] = _CLIP8(g), pDst[iR] = _CLIP8(r); + } + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn); + break; + + case CF_RGBE: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = ((pSrcY[iPos] * cMul) >> rShiftY), r = - ((pSrcU[iPos] * cMul) >> rShiftUV), b = ((pSrcV[iPos] * cMul) >> rShiftUV); + + _ICC(r, g, b); + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + inverseConvertRGBE (r, g, b, pDst, pDst + 1, pDst + 2, pDst + 3); + } + } + break; + + case CMYK: + { + PixelI * pSrcK = pSC->a0MBbuffer[3]; + PixelI iBias1 = (128 << rShiftY) / cMul, iBias2 = (((128 << rShiftUV) / cMul) >> 1); + + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI m = ((-pSrcY[iPos] + iBias1) * cMul) >> rShiftY, c = (pSrcU[iPos] * cMul) >> rShiftUV, y = -(pSrcV[iPos] * cMul) >> rShiftUV, k = ((pSrcK[iPos] + iBias2) * cMul) >> rShiftUV; + + _ICC_CMYK(c, m, y, k); + + pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + pDst[0] = _CLIP8(c), pDst[1] = _CLIP8(m), pDst[2] = _CLIP8(y), pDst[3] = _CLIP8(k); + } + } + break; + } + default: + assert(0); + break; + } + } + if(bd == BD_16){ + U16 * pDst; + + offset = (((1 << 15) >> nLen) << rShiftY) / cMul; + + switch(cfExt){ + case CF_RGB: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + r <<= nLen, g <<= nLen, b <<= nLen; + pDst[0] = _CLIPU16(r); + pDst[1] = _CLIPU16(g); + pDst[2] = _CLIPU16(b); + } + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn); + break; + + case CMYK: + { + PixelI * pSrcK = pSC->a0MBbuffer[3]; + PixelI iBias1 = (32768 << rShiftY) / cMul, iBias2 = (((32768 << rShiftUV) / cMul) >> 1); + + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI m = ((-pSrcY[iPos] + iBias1) * cMul) >> rShiftY, c = (pSrcU[iPos] * cMul) >> rShiftUV, y = -(pSrcV[iPos] * cMul) >> rShiftUV, k = ((pSrcK[iPos] + iBias2) * cMul) >> rShiftUV; + + _ICC_CMYK(c, m, y, k); + + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + c <<= nLen, m <<= nLen, y <<= nLen, k <<= nLen; + pDst[0] = _CLIPU16(c); + pDst[1] = _CLIPU16(m); + pDst[2] = _CLIPU16(y); + pDst[3] = _CLIPU16(k); + } + } + break; + } + default: + assert(0); + break; + } + } + if(bd == BD_16S){ + I16 * pDst; + + switch(cfExt){ + case CF_RGB: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = (pSrcY[iPos] * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + + pDst = (I16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + r <<= nLen, g <<= nLen, b <<= nLen; + pDst[0] = _CLIP16(r); + pDst[1] = _CLIP16(g); + pDst[2] = _CLIP16(b); + } + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn); + break; + + case CMYK: + { + PixelI * pSrcK = pSC->a0MBbuffer[3]; + + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI m = -(pSrcY[iPos] * cMul) >> rShiftY, c = (pSrcU[iPos] * cMul) >> rShiftUV, y = -(pSrcV[iPos] * cMul) >> rShiftUV, k = (pSrcK[iPos] * cMul) >> rShiftUV; + + _ICC_CMYK(c, m, y, k); + + pDst = (I16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + c <<= nLen, m <<= nLen, y <<= nLen, k <<= nLen; + pDst[0] = _CLIP16(c); + pDst[1] = _CLIP16(m); + pDst[2] = _CLIP16(y); + pDst[3] = _CLIP16(k); + } + } + } + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_16F){ + U16 * pDst; + + switch(cfExt){ + case CF_RGB: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = (pSrcY[iPos] * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + pDst[0] = backwardHalf (r); + pDst[1] = backwardHalf (g); + pDst[2] = backwardHalf (b); + } + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn); + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_32){ + U32 * pDst; + + offset = (((1 << 31) >> nLen) << rShiftY) / cMul; + + switch(cfExt){ + case CF_RGB: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + + pDst = (U32 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + + pDst[0] = (U32)(r << nLen); + pDst[1] = (U32)(g << nLen); + pDst[2] = (U32)(b << nLen); + } + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn); + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_32S){ + I32 * pDst; + + switch(cfExt){ + case CF_RGB: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = (pSrcY[iPos] * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + + pDst = (I32 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + pDst[0] = (I32)(r << nLen); + pDst[1] = (I32)(g << nLen); + pDst[2] = (I32)(b << nLen); + } + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn); + break; + + default: + assert(0); + break; + } + } + + else if(bd == BD_32F){ + float * pDst; + + switch(cfExt){ + case CF_RGB: + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = (pSrcY[iPos] * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + + pDst = (float *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + pDst[0] = pixel2float (r, nExpBias, nLen); + pDst[1] = pixel2float (g, nExpBias, nLen); + pDst[2] = pixel2float (b, nExpBias, nLen); + } + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn); + break; + + default: + assert(0); + break; + } + } + else if(bd == BD_1){ + const size_t iPos = pSC->WMII.cLeadingPadding; + Bool bBW; + U8 cByte, cShift; + assert(cfExt == Y_ONLY && pSC->m_param.cfColorFormat == Y_ONLY); + + if(pSC->WMII.oOrientation < O_RCW){ + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits] + iPos; iColumn < cWidth; iColumn += tScale){ + bBW = (pSC->WMISCP.bBlackWhite ^ (pSrcY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] > 0)); + cByte = ((U8 *)pSC->WMIBI.pv + (pOffsetX[iColumn >> nBits] >> 3) + iY)[0]; + cShift = (U8)(7 - (pOffsetX[iColumn >> nBits] & 7)); + ((U8 *)pSC->WMIBI.pv + (pOffsetX[iColumn >> nBits] >> 3) + iY)[0] ^= ((((bBW + (cByte >> cShift)) & 0x1)) << cShift); + } + } + else{ + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits] + iPos; iColumn < cWidth; iColumn += tScale){ + bBW = (pSC->WMISCP.bBlackWhite ^ (pSrcY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] > 0)); + cByte = ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + (iY >> 3))[0]; + cShift = (U8)(7 - (iY & 7)); + ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + (iY >> 3))[0] ^= ((((bBW + (cByte >> cShift)) & 0x1)) << cShift); + } + } + } + else if(bd == BD_5){ + U16 * pDst; + + offset = (16 << rShiftY) / cMul; + + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + pDst[0] = (U16)_CLIP2(0, r, 31) + (((U16)_CLIP2(0, g, 31)) << 5) + (((U16)_CLIP2(0, b, 31)) << 10); + } + } + } + else if(bd == BD_565){ + U16 * pDst; + + offset = (32 << rShiftY) / cMul; + + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + r /= 2, b /= 2; + pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + pDst[0] = (U16)_CLIP2(0, r, 31) + (((U16)_CLIP2(0, g, 63)) << 5) + (((U16)_CLIP2(0, b, 31)) << 11); + } + } + } + else if(bd == BD_10){ + U32 * pDst; + + offset = (512 << rShiftY) / cMul; + + for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){ + for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){ + size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV; + + _ICC(r, g, b); + pDst = (U32 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY; + pDst[0] = (U32)_CLIP2(0, r, 1023) + + (((U32)_CLIP2(0, g, 1023)) << 10) + + (((U32)_CLIP2(0, b, 1023)) << 20); + } + } + } + + if(pSC->WMISCP.uAlphaMode > 0) + if(decodeThumbnailAlpha(pSC, nBits, cMul, rShiftY) != ICERR_OK) + return ICERR_ERROR; + +#ifdef REENTRANT_MODE + pSC->WMIBI.cLinesDecoded = ( cHeight - iFirstRow + tScale - 1 ) / tScale; + if (CF_RGB == pSC->WMII.cfColorFormat && Y_ONLY == pSC->WMISCP.cfColorFormat) + { + const CWMImageInfo* pII = &pSC->WMII; + +#define fixupThumb(type, nCh) \ +for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) {\ + size_t iOffsetY;\ + for(iColumn = iFirstColumn, iOffsetY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){\ + type *pT = (type*)((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iOffsetY);\ + pT[iB] = pT[1] = pT[iR]; \ + } \ +} \ +break + + switch (pII->bdBitDepth) + { + case BD_8: + fixupThumb(U8, (pII->cBitsPerUnit >> 3)); + break; + + case BD_16: + case BD_16S: + case BD_16F: + fixupThumb(U16, (pII->cBitsPerUnit >> 3) / sizeof(U16)); + break; + + case BD_32: + case BD_32S: + case BD_32F: + fixupThumb(U32, (pII->cBitsPerUnit >> 3) / sizeof(float)); + break; + + case BD_5: + case BD_10: + case BD_565: + default: + break; + } + } +#endif + + return ICERR_OK; +} + +/************************************************************************* + Read variable length byte aligned integer +*************************************************************************/ +static size_t GetVLWordEsc(BitIOInfo* pIO, Int *iEscape) +{ + size_t s; + + if (iEscape) + *iEscape = 0; + + s = getBit32(pIO, 8); + if (s == 0xfd || s == 0xfe || s == 0xff) { + if (iEscape) + *iEscape = (Int) s; + s = 0; + } + else if (s < 0xfb) { + s = (s << 8) | getBit32(pIO, 8); + } + else { + s -= 0xfb; + if (s) { + s = getBit32(pIO, 16) << 16; + s = (s | getBit32(pIO, 16)) << 16; + s <<= 16; + } + s |= (getBit32(pIO, 16) << 16); + s |= getBit32(pIO, 16); + } + return s; +} + +//================================================================ +Int readIndexTable(CWMImageStrCodec * pSC) +{ + BitIOInfo* pIO = pSC->pIOHeader; + readIS_L1(pSC, pIO); + + if(pSC->cNumBitIO > 0){ + size_t *pTable = pSC->pIndexTable; + U32 iEntry = (U32)pSC->cNumBitIO * (pSC->WMISCP.cNumOfSliceMinus1H + 1), i; + + // read index table header [0x0001] - 2 bytes + if (getBit32(pIO, 16) != 1) + return ICERR_ERROR; + + //iBits = getBit16(pIO, 5) + 1; // how many bits per entry + for(i = 0; i < iEntry; i ++){ + readIS_L1(pSC, pIO); + pTable[i] = GetVLWordEsc(pIO, NULL); // escape handling is not important since the respective band is not accessed + } + } + + pSC->cHeaderSize = GetVLWordEsc(pIO, NULL); // escape handling is not important + flushToByte(pIO); + + pSC->cHeaderSize += getPosRead(pSC->pIOHeader); // get header length + + return ICERR_OK; +} + +Int StrIODecInit(CWMImageStrCodec* pSC) +{ + if(allocateBitIOInfo(pSC) != ICERR_OK){ + return ICERR_ERROR; + } + + attachISRead(pSC->pIOHeader, pSC->WMISCP.pWStream, pSC); + + readIndexTable(pSC); + + if(pSC->WMISCP.bVerbose){ + U32 i, j; + + printf("\n%d horizontal tiles:\n", pSC->WMISCP.cNumOfSliceMinus1H + 1); + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1H; i ++){ + printf(" offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileY[i]); + } + + printf("\n%d vertical tiles:\n", pSC->WMISCP.cNumOfSliceMinus1V + 1); + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){ + printf(" offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileX[i]); + } + + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){ + printf("\nSpatial order bitstream\n"); + } + else{ + printf("\nFrequency order bitstream\n"); + } + + if(!pSC->m_param.bIndexTable){ + printf("\nstreaming mode, no index table.\n"); + } + else if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){ + for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){ + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){ + size_t * p = &pSC->pIndexTable[j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i]; + if(i + j != pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V){ + printf("bitstream size for tile (%d, %d): %d.\n", j, i, (int) (p[1] - p[0])); + } + else{ + printf("bitstream size for tile (%d, %d): unknown.\n", j, i); + } + } + } + } + else{ + for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){ + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){ + size_t * p = &pSC->pIndexTable[(j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i) * 4]; + if(i + j != pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V){ + printf("bitstream size of (DC, LP, AC, FL) for tile (%d, %d): %d %d %d %d.\n", j, i, + (int) (p[1] - p[0]), (int) (p[2] - p[1]), (int) (p[3] - p[2]), (int) (p[4] - p[3])); + } + else{ + printf("bitstream size of (DC, LP, AC, FL) for tile (%d, %d): %d %d %d unknown.\n", j, i, + (int) (p[1] - p[0]), (int) (p[2] - p[1]), (int) (p[3] - p[2])); + } + } + } + } + } + + return 0; +} + +Int StrIODecTerm(CWMImageStrCodec* pSC) +{ + detachISRead(pSC, pSC->pIOHeader); + + free(pSC->m_ppBitIO); + free(pSC->pIndexTable); + + return 0; +} + +Int initLookupTables(CWMImageStrCodec* pSC) +{ + static const U8 cbChannels[BDB_MAX] = {1, 1, 2, 2, 2, 4, 4, 4, (U8) -1, (U8) -1, (U8) -1 }; + + CWMImageInfo * pII = &pSC->WMII; + size_t cStrideX, cStrideY; + size_t w, h, i, iFirst = 0; + Bool bReverse; + + // lookup tables for rotation and flipping + if(pSC->m_Dparam->cThumbnailScale > 1) // thumbnail + w = pII->cThumbnailWidth, h = pII->cThumbnailHeight; + else + w = pII->cWidth, h = pII->cHeight; + w += (pSC->m_Dparam->cROILeftX + pSC->m_Dparam->cThumbnailScale - 1) / pSC->m_Dparam->cThumbnailScale; + h += (pSC->m_Dparam->cROITopY + pSC->m_Dparam->cThumbnailScale - 1) / pSC->m_Dparam->cThumbnailScale; + + switch(pII->bdBitDepth){ + case BD_16: + case BD_16S: + case BD_5: + case BD_565: + case BD_16F: + cStrideY = pSC->WMIBI.cbStride / 2; + break; + + case BD_32: + case BD_32S: + case BD_32F: + case BD_10: + cStrideY = pSC->WMIBI.cbStride / 4; + break; + + default: //BD_8, BD_1 + cStrideY = pSC->WMIBI.cbStride; + break; + } + + switch(pII->cfColorFormat){ + case YUV_420: + cStrideX = 6; + w >>= 1, h >>= 1; + break; + + case YUV_422: + cStrideX = 4; + w >>= 1; + break; + + default: + cStrideX = (pII->cBitsPerUnit >> 3) / cbChannels[pII->bdBitDepth]; + break; + } + + if(pII->bdBitDepth == BD_1 || pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_10 || pII->bdBitDepth == BD_565) + cStrideX = 1; + + if(pII->oOrientation > O_FLIPVH) // rotated !! + i =cStrideX, cStrideX = cStrideY, cStrideY = i; + + pSC->m_Dparam->pOffsetX = (size_t *)malloc(w * sizeof(size_t)); + if(pSC->m_Dparam->pOffsetX == NULL || w * sizeof(size_t) < w) + return ICERR_ERROR; + /* + consider a row in the source image. if it becomes a reversed row in the target, or a reversed (upside-down)column + in the target, we have to reverse the offsets. bReverse here tells us when this happened. + */ + bReverse = (pII->oOrientation == O_FLIPH || pII->oOrientation == O_FLIPVH || + pII->oOrientation == O_RCW_FLIPV || pII->oOrientation == O_RCW_FLIPVH); + if(!pSC->m_Dparam->bDecodeFullFrame) // take care of region decode here! + iFirst = (pSC->m_Dparam->cROILeftX + pSC->m_Dparam->cThumbnailScale - 1) / pSC->m_Dparam->cThumbnailScale; + for(i = 0; i + iFirst < w; i ++){ + pSC->m_Dparam->pOffsetX[i + iFirst] = pII->cLeadingPadding + (bReverse ? (pSC->m_Dparam->bDecodeFullFrame ? w : + (pSC->m_Dparam->cROIRightX - pSC->m_Dparam->cROILeftX + pSC->m_Dparam->cThumbnailScale) / pSC->m_Dparam->cThumbnailScale / ((pII->cfColorFormat == YUV_420 || pII->cfColorFormat == YUV_422) ? 2 : 1)) - 1 - i : i) * cStrideX; + } + + pSC->m_Dparam->pOffsetY = (size_t *)malloc(h * sizeof(size_t)); + if(pSC->m_Dparam->pOffsetY == NULL || h * sizeof(size_t) < h) + return ICERR_ERROR; + /* + consider a column in the source image. if it becomes an upside-down column in the target, or a reversed row + in the target, we have to reverse the offsets. bReverse here tells us when this happened. + */ + bReverse = (pII->oOrientation == O_FLIPV || pII->oOrientation == O_FLIPVH || + pII->oOrientation == O_RCW || pII->oOrientation == O_RCW_FLIPV); + if(!pSC->m_Dparam->bDecodeFullFrame) // take care of region decode here! + iFirst = (pSC->m_Dparam->cROITopY + pSC->m_Dparam->cThumbnailScale - 1) / pSC->m_Dparam->cThumbnailScale; + for(i = 0; i + iFirst < h; i ++){ + pSC->m_Dparam->pOffsetY[i + iFirst] = (bReverse ? (pSC->m_Dparam->bDecodeFullFrame ? h : + (pSC->m_Dparam->cROIBottomY - pSC->m_Dparam->cROITopY + pSC->m_Dparam->cThumbnailScale) / pSC->m_Dparam->cThumbnailScale / (pII->cfColorFormat == YUV_420 ? 2 : 1)) - 1 - i : i) * cStrideY; + } + + return ICERR_OK; +} + +Void setROI(CWMImageStrCodec* pSC) +{ + CWMImageInfo * pWMII = &pSC->WMII; + CWMIStrCodecParam * pSCP = &pSC->WMISCP; + + // inscribed image size + pWMII->cWidth -= pSC->m_param.cExtraPixelsLeft + pSC->m_param.cExtraPixelsRight; + pWMII->cHeight -= pSC->m_param.cExtraPixelsTop + pSC->m_param.cExtraPixelsBottom; + + pSC->m_Dparam->bSkipFlexbits = (pSCP->sbSubband == SB_NO_FLEXBITS); + pSC->m_Dparam->bDecodeHP = (pSCP->sbSubband == SB_ALL || pSCP->sbSubband == SB_NO_FLEXBITS); + pSC->m_Dparam->bDecodeLP = (pSCP->sbSubband != SB_DC_ONLY); + pSC->m_Dparam->cThumbnailScale = 1; + while(pSC->m_Dparam->cThumbnailScale * pWMII->cThumbnailWidth < pWMII->cWidth) + pSC->m_Dparam->cThumbnailScale <<= 1; + if(pSC->WMISCP.bfBitstreamFormat == FREQUENCY){ + if(pSC->m_Dparam->cThumbnailScale >= 4) + pSC->m_Dparam->bDecodeHP = FALSE; // no need to decode HP + if(pSC->m_Dparam->cThumbnailScale >= 16) + pSC->m_Dparam->bDecodeLP = FALSE; // only need to decode DC + } + + // original image size + pWMII->cWidth += pSC->m_param.cExtraPixelsLeft + pSC->m_param.cExtraPixelsRight; + pWMII->cHeight += pSC->m_param.cExtraPixelsTop + pSC->m_param.cExtraPixelsBottom; + + /** region decode stuff */ + pSC->m_Dparam->cROILeftX = pWMII->cROILeftX * pSC->m_Dparam->cThumbnailScale + pSC->m_param.cExtraPixelsLeft; + pSC->m_Dparam->cROIRightX = pSC->m_Dparam->cROILeftX + pWMII->cROIWidth * pSC->m_Dparam->cThumbnailScale - 1; + pSC->m_Dparam->cROITopY = pWMII->cROITopY * pSC->m_Dparam->cThumbnailScale + pSC->m_param.cExtraPixelsTop; + pSC->m_Dparam->cROIBottomY = pSC->m_Dparam->cROITopY + pWMII->cROIHeight * pSC->m_Dparam->cThumbnailScale - 1; + if(pSC->m_Dparam->cROIRightX >= pWMII->cWidth) + pSC->m_Dparam->cROIRightX = pWMII->cWidth - 1; + if(pSC->m_Dparam->cROIBottomY >= pWMII->cHeight) + pSC->m_Dparam->cROIBottomY = pWMII->cHeight - 1; + + pSC->m_Dparam->bDecodeFullFrame = (pSC->m_Dparam->cROILeftX + pSC->m_Dparam->cROITopY == 0 && + ((pSC->m_Dparam->cROIRightX + 15) / 16 >= (pWMII->cWidth + 14) / 16) && ((pSC->m_Dparam->cROIBottomY + 15) / 16 >= (pWMII->cHeight + 14) / 16)); + + pSC->m_Dparam->bDecodeFullWidth = (pSC->m_Dparam->cROILeftX == 0 && ((pSC->m_Dparam->cROIRightX + 15) / 16 >= (pWMII->cWidth + 14) / 16)); + + // inscribed image size + pWMII->cWidth -= pSC->m_param.cExtraPixelsLeft + pSC->m_param.cExtraPixelsRight; + pWMII->cHeight -= pSC->m_param.cExtraPixelsTop + pSC->m_param.cExtraPixelsBottom; + + if(pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pWMII->bSkipFlexbits == TRUE) + pSC->m_Dparam->bSkipFlexbits = TRUE; + + pSC->cTileColumn = pSC->cTileRow = 0; +} + +Int StrDecInit(CWMImageStrCodec* pSC) +{ + // CWMImageInfo * pWMII = &pSC->WMII; + COLORFORMAT cfInt = pSC->m_param.cfColorFormat; + COLORFORMAT cfExt = pSC->WMII.cfColorFormat; + size_t i; + + /** color transcoding with resolution change **/ + pSC->m_bUVResolutionChange = ((cfExt != Y_ONLY) && ((cfInt == YUV_420 && cfExt != YUV_420) || + (cfInt == YUV_422 && cfExt != YUV_422))) && !pSC->WMISCP.bYUVData; + if(pSC->m_bUVResolutionChange){ + pSC->pResU = (PixelI *)malloc((cfExt == YUV_422 ? 128 : 256) * pSC->cmbWidth * sizeof(PixelI)); + pSC->pResV = (PixelI *)malloc((cfExt == YUV_422 ? 128 : 256) * pSC->cmbWidth * sizeof(PixelI)); + if(pSC->pResU == NULL || pSC->pResV == NULL || (cfExt == YUV_422 ? 128 : 256) * pSC->cmbWidth * sizeof(PixelI) < pSC->cmbWidth){ + return ICERR_ERROR; + } + } + + if(allocatePredInfo(pSC) != ICERR_OK){ + return ICERR_ERROR; + } + + if(allocateTileInfo(pSC) != ICERR_OK) + return ICERR_ERROR; + + if((pSC->m_param.uQPMode & 1) == 0){ // DC frame uniform quantization + if(allocateQuantizer(pSC->pTile[0].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK) + return ICERR_ERROR; + setUniformQuantizer(pSC, 0); + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + pSC->pTile[0].pQuantizerDC[i]->iIndex = pSC->m_param.uiQPIndexDC[i]; + formatQuantizer(pSC->pTile[0].pQuantizerDC, (pSC->m_param.uQPMode >> 3) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith); + } + + if(pSC->WMISCP.sbSubband != SB_DC_ONLY){ + if((pSC->m_param.uQPMode & 2) == 0){ // LP frame uniform quantization + if(allocateQuantizer(pSC->pTile[0].pQuantizerLP, pSC->m_param.cNumChannels, 1) != ICERR_OK) + return ICERR_ERROR; + setUniformQuantizer(pSC, 1); + if((pSC->m_param.uQPMode & 0x200) == 0) // use DC quantizer + useDCQuantizer(pSC, 0); + else{ + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + pSC->pTile[0].pQuantizerLP[i]->iIndex = pSC->m_param.uiQPIndexLP[i]; + formatQuantizer(pSC->pTile[0].pQuantizerLP, (pSC->m_param.uQPMode >> 5) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith); + } + } + + if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){ + if((pSC->m_param.uQPMode & 4) == 0){ // HP frame uniform quantization + if(allocateQuantizer(pSC->pTile[0].pQuantizerHP, pSC->m_param.cNumChannels, 1) != ICERR_OK) + return ICERR_ERROR; + setUniformQuantizer(pSC, 2); + + if((pSC->m_param.uQPMode & 0x400) == 0) // use LP quantizer + useLPQuantizer(pSC, 1, 0); + else{ + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + pSC->pTile[0].pQuantizerHP[i]->iIndex = pSC->m_param.uiQPIndexHP[i]; + formatQuantizer(pSC->pTile[0].pQuantizerHP, (pSC->m_param.uQPMode >> 7) & 3, pSC->m_param.cNumChannels, 0, FALSE, pSC->m_param.bScaledArith); + } + } + } + } + + if(pSC->WMISCP.cNumOfSliceMinus1V >= MAX_TILES || AllocateCodingContextDec(pSC, pSC->WMISCP.cNumOfSliceMinus1V + 1) != ICERR_OK){ + return ICERR_ERROR; + } + + if (pSC->m_bSecondary) { + pSC->pIOHeader = pSC->m_pNextSC->pIOHeader; + pSC->m_ppBitIO = pSC->m_pNextSC->m_ppBitIO; + pSC->cNumBitIO = pSC->m_pNextSC->cNumBitIO; + pSC->cSB = pSC->m_pNextSC->cSB; + } + + setBitIOPointers(pSC); + + return ICERR_OK; +} + +Int StrDecTerm(CWMImageStrCodec* pSC) +{ + size_t j, jend = (pSC->m_pNextSC != NULL); + + for (j = 0; j <= jend; j++) { + if(pSC->m_bUVResolutionChange){ + if(pSC->pResU != NULL) + free(pSC->pResU); + if(pSC->pResV != NULL) + free(pSC->pResV); + } + + freePredInfo(pSC); + + freeTileInfo(pSC); + + FreeCodingContextDec(pSC); + + if (j == 0) { + StrIODecTerm(pSC); + + // free lookup tables for rotation and flipping + if(pSC->m_Dparam->pOffsetX != NULL) + free(pSC->m_Dparam->pOffsetX); + if(pSC->m_Dparam->pOffsetY != NULL) + free(pSC->m_Dparam->pOffsetY); + } + + pSC = pSC->m_pNextSC; + } + + return 0; +} + +/************************************************************************* + Read header of image plane +*************************************************************************/ +Int ReadImagePlaneHeader(CWMImageInfo* pII, CWMIStrCodecParam *pSCP, + CCoreParameters *pSC, SimpleBitIO* pSB) +{ + ERR err = WMP_errSuccess; + + pSC->cfColorFormat = getBit32_SB(pSB, 3); // internal color format + FailIf((pSC->cfColorFormat < Y_ONLY || pSC->cfColorFormat > NCOMPONENT), WMP_errUnsupportedFormat); + pSCP->cfColorFormat = pSC->cfColorFormat; // this should be removed later + pSC->bScaledArith = getBit32_SB(pSB, 1); // lossless mode + + // subbands + pSCP->sbSubband = getBit32_SB(pSB, 4); + +// color parameters + switch (pSC->cfColorFormat) { + case Y_ONLY: + pSC->cNumChannels = 1; + break; + case YUV_420: + pSC->cNumChannels = 3; + getBit32_SB(pSB, 1); + pII->cChromaCenteringX = (U8) getBit32_SB(pSB, 3); + getBit32_SB(pSB, 1); + pII->cChromaCenteringY = (U8) getBit32_SB(pSB, 3); + break; + case YUV_422: + pSC->cNumChannels = 3; + getBit32_SB(pSB, 1); + pII->cChromaCenteringX = (U8) getBit32_SB(pSB, 3); + getBit32_SB(pSB, 4); + break; + case YUV_444: + pSC->cNumChannels = 3; + getBit32_SB(pSB, 4); + getBit32_SB(pSB, 4); + break; + case NCOMPONENT: + pSC->cNumChannels = (Int) getBit32_SB(pSB, 4) + 1; + getBit32_SB(pSB, 4); + break; + case CMYK: + pSC->cNumChannels = 4; + break; + default: + break; + } + +// float and 32s additional parameters + switch (pII->bdBitDepth) { + case BD_16: + case BD_16S: + case BD_32: + case BD_32S: + pSCP->nLenMantissaOrShift = (U8) getBit32_SB(pSB, 8); + break; + case BD_32F: + pSCP->nLenMantissaOrShift = (U8) getBit32_SB(pSB, 8);//float conversion parameters + pSCP->nExpBias = (I8) getBit32_SB(pSB, 8); + break; + default: + break; + } + + // quantization + pSC->uQPMode = 0; + if(getBit32_SB(pSB, 1) == 1) // DC uniform + pSC->uQPMode += (readQuantizerSB(pSC->uiQPIndexDC, pSB, pSC->cNumChannels) << 3); + else + pSC->uQPMode ++; + if(pSCP->sbSubband != SB_DC_ONLY){ + if(getBit32_SB(pSB, 1) == 0){ // don't use DC QP + pSC->uQPMode += 0x200; + if(getBit32_SB(pSB, 1) == 1) // LP uniform + pSC->uQPMode += (readQuantizerSB(pSC->uiQPIndexLP, pSB, pSC->cNumChannels) << 5); + else + pSC->uQPMode += 2; + } + else + pSC->uQPMode += ((pSC->uQPMode & 1) << 1) + ((pSC->uQPMode & 0x18) << 2); + + if(pSCP->sbSubband != SB_NO_HIGHPASS){ + if(getBit32_SB(pSB, 1) == 0){ // don't use LP QP + pSC->uQPMode += 0x400; + if(getBit32_SB(pSB, 1) == 1) // HP uniform + pSC->uQPMode += (readQuantizerSB(pSC->uiQPIndexHP, pSB, pSC->cNumChannels) << 7); + else + pSC->uQPMode += 4; + } + else + pSC->uQPMode += ((pSC->uQPMode & 2) << 1) + ((pSC->uQPMode & 0x60) << 2); + } + } + + if(pSCP->sbSubband == SB_DC_ONLY) + pSC->uQPMode |= 0x200; + else if(pSCP->sbSubband == SB_NO_HIGHPASS) + pSC->uQPMode |= 0x400; + + + FailIf((pSC->uQPMode & 0x600) == 0, WMP_errInvalidParameter); // frame level QPs must be specified independently! + + flushToByte_SB(pSB); // remove this later + +Cleanup: + return WMP_errSuccess == err ? ICERR_OK : ICERR_ERROR; +} + +/************************************************************************* + Read header of image, and header of FIRST PLANE only +*************************************************************************/ +Int ReadWMIHeader( + CWMImageInfo* pII, + CWMIStrCodecParam *pSCP, + CCoreParameters *pSC) +{ + U32 i; + ERR err = WMP_errSuccess; + Bool bTilingPresent, bInscribed, bTileStretch, bAbbreviatedHeader; + struct WMPStream* pWS = pSCP->pWStream; + + SimpleBitIO SB = {0}; + SimpleBitIO* pSB = &SB; + + U8 szMS[8] = {0}; + U32 cbStream = 0; + + // U32 bits = 0; + // Int HEADERSIZE = 0; + + assert(pSC != NULL); + //================================ +// 0 + /** signature **/ + Call(pWS->Read(pWS, szMS, sizeof(szMS))); + FailIf(szMS != (U8 *) strstr((char *) szMS, "WMPHOTO"), WMP_errUnsupportedFormat); + //================================ + Call(attach_SB(pSB, pWS)); + +// 8 + /** codec version and subversion **/ + i = getBit32_SB(pSB, 4); + FailIf((i != CODEC_VERSION), WMP_errIncorrectCodecVersion); + pSC->cVersion = i; + i = getBit32_SB(pSB, 4); // subversion + FailIf((i != CODEC_SUBVERSION && + i != CODEC_SUBVERSION_NEWSCALING_SOFT_TILES && i != CODEC_SUBVERSION_NEWSCALING_HARD_TILES), + WMP_errIncorrectCodecSubVersion); + pSC->cSubVersion = i; + + pSC->bUseHardTileBoundaries = FALSE; + if (pSC->cSubVersion == CODEC_SUBVERSION_NEWSCALING_HARD_TILES) + pSC->bUseHardTileBoundaries = TRUE; + + pSCP->bUseHardTileBoundaries = pSC->bUseHardTileBoundaries; + +// 9 primary parameters + bTilingPresent = (Bool) getBit32_SB(pSB, 1); // tiling present + pSCP->bfBitstreamFormat = getBit32_SB(pSB, 1); // bitstream layout + pII->oOrientation = (ORIENTATION)getBit32_SB(pSB, 3); // presentation orientation + pSC->bIndexTable = getBit32_SB(pSB, 1); + i = getBit32_SB(pSB, 2); // overlap + FailIf((i == 3), WMP_errInvalidParameter); + pSCP->olOverlap = i; + +// 11 some other parameters + bAbbreviatedHeader = (Bool) getBit32_SB(pSB, 1); // short words for size and tiles + pSCP->bdBitDepth = (BITDEPTH) getBit32_SB(pSB, 1); // long word +pSCP->bdBitDepth = BD_LONG; // remove when optimization is done + bInscribed = (Bool) getBit32_SB(pSB, 1); // windowing + pSC->bTrimFlexbitsFlag = (Bool) getBit32_SB(pSB, 1); // trim flexbits flag + bTileStretch = (Bool) getBit32_SB(pSB, 1); // tile stretching flag + pSC->bRBSwapped = (Bool) getBit32_SB(pSB, 1); // red-blue swap flag + getBit32_SB(pSB, 1); // padding / reserved bit + pSC->bAlphaChannel = (Bool) getBit32_SB(pSB, 1); // alpha channel present + +// 10 - informational + pII->cfColorFormat = getBit32_SB(pSB, 4); // source color format + pII->bdBitDepth = getBit32_SB(pSB, 4); // source bit depth + + if(BD_1alt == pII->bdBitDepth) + { + pII->bdBitDepth = BD_1; + pSCP->bBlackWhite = 1; + } + +// 12 - Variable length fields +// size + pII->cWidth = getBit32_SB(pSB, bAbbreviatedHeader ? 16 : 32) + 1; + pII->cHeight = getBit32_SB(pSB, bAbbreviatedHeader ? 16 : 32) + 1; + pSC->cExtraPixelsTop = pSC->cExtraPixelsLeft = pSC->cExtraPixelsBottom = pSC->cExtraPixelsRight = 0; + if (bInscribed == FALSE && (pII->cWidth & 0xf) != 0) + pSC->cExtraPixelsRight = 0x10 - (pII->cWidth & 0xF); + if (bInscribed == FALSE && (pII->cHeight & 0xf) != 0) + pSC->cExtraPixelsBottom = 0x10 - (pII->cHeight & 0xF); + +// tiling + pSCP->cNumOfSliceMinus1V = pSCP->cNumOfSliceMinus1H = 0; + if (bTilingPresent) { + pSCP->cNumOfSliceMinus1V = getBit32_SB(pSB, LOG_MAX_TILES); // # of vertical slices along X axis + pSCP->cNumOfSliceMinus1H = getBit32_SB(pSB, LOG_MAX_TILES); // # of horizontal slices along Y axis + } + FailIf((pSC->bIndexTable == FALSE) && (pSCP->bfBitstreamFormat == FREQUENCY || pSCP->cNumOfSliceMinus1V + pSCP->cNumOfSliceMinus1H > 0), + WMP_errUnsupportedFormat); + +// tile sizes + pSCP->uiTileX[0] = pSCP->uiTileY[0] = 0; + for(i = 0; i < pSCP->cNumOfSliceMinus1V; i ++){ // width in MB of vertical slices, not needed for last slice! + pSCP->uiTileX[i + 1] = (U32) getBit32_SB(pSB, bAbbreviatedHeader ? 8 : 16) + pSCP->uiTileX[i]; + } + for(i = 0; i < pSCP->cNumOfSliceMinus1H; i ++){ // width in MB of vertical slices, not needed for last slice! + pSCP->uiTileY[i + 1] = (U32) getBit32_SB(pSB, bAbbreviatedHeader ? 8 : 16) + pSCP->uiTileY[i]; + } + if (bTileStretch) { // no handling of tile stretching enabled as of now + for (i = 0; i < (pSCP->cNumOfSliceMinus1V + 1) * (pSCP->cNumOfSliceMinus1H + 1); i++) + getBit32_SB(pSB, 8); + } + +// window due to compressed domain processing + if (bInscribed) { + pSC->cExtraPixelsTop = (U8)getBit32_SB(pSB, 6); + pSC->cExtraPixelsLeft = (U8)getBit32_SB(pSB, 6); + pSC->cExtraPixelsBottom = (U8)getBit32_SB(pSB, 6); + pSC->cExtraPixelsRight = (U8)getBit32_SB(pSB, 6); + } + + if(((pII->cWidth + pSC->cExtraPixelsLeft + pSC->cExtraPixelsRight) & 0xf) + ((pII->cHeight + pSC->cExtraPixelsTop + pSC->cExtraPixelsBottom) & 0xf) != 0){ + FailIf((pII->cWidth & 0xf) + (pII->cHeight & 0xf) + pSC->cExtraPixelsLeft + pSC->cExtraPixelsTop != 0, WMP_errInvalidParameter); + FailIf(pII->cWidth <= pSC->cExtraPixelsRight || pII->cHeight <= pSC->cExtraPixelsBottom, WMP_errInvalidParameter); + pII->cWidth -= pSC->cExtraPixelsRight, pII->cHeight -= pSC->cExtraPixelsBottom; + } + + flushToByte_SB(pSB); // redundant + + // read header of first image plane + FailIf(ReadImagePlaneHeader(pII, pSCP, pSC, pSB), WMP_errUnsupportedFormat); + + // maybe UNALIGNED!!! + + //================================ + detach_SB(pSB); + pSCP->cbStream = cbStream - getByteRead_SB(pSB); + + pSCP->uAlphaMode = (pSC->bAlphaChannel ? pSCP->uAlphaMode : 0); + pSCP->cChannel = pSC->cNumChannels; + + if((pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_10 || pII->bdBitDepth == BD_565) && + (pSCP->cfColorFormat != YUV_444 && pSCP->cfColorFormat != YUV_422 && pSCP->cfColorFormat != YUV_420 && pSCP->cfColorFormat != Y_ONLY)) + return ICERR_ERROR; + +Cleanup: + return WMP_errSuccess == err ? ICERR_OK : ICERR_ERROR; +} + +//---------------------------------------------------------------- +// streaming api init/decode/term +EXTERN_C Int ImageStrDecGetInfo( + CWMImageInfo* pII, + CWMIStrCodecParam *pSCP) +{ + ERR err = WMP_errSuccess; + size_t cMarker; + CCoreParameters aDummy; + // mark position of start of data + Call(pSCP->pWStream->GetPos(pSCP->pWStream, &cMarker)); + Call(ReadWMIHeader(pII, pSCP, &aDummy)); + // rewind to start of data + Call(pSCP->pWStream->SetPos(pSCP->pWStream, cMarker)); + return ICERR_OK; + +Cleanup: + return ICERR_ERROR; +} + +EXTERN_C Int WMPhotoValidate( + CWMImageInfo * pII, + CWMIStrCodecParam * pSCP) +{ + CWMImageInfo cII; + CWMIStrCodecParam cSCP = *pSCP; + size_t cScale = 1; + + if(ImageStrDecGetInfo(&cII, pSCP) != ICERR_OK) + return ICERR_ERROR; + + // copy over un-overwritable ImageInfo parameters + pII->bdBitDepth = cII.bdBitDepth; + pII->cWidth = cII.cWidth; + pII->cHeight = cII.cHeight; + + if(pII->cWidth == 0 || pII->cHeight == 0) + return ICERR_ERROR; + + // copy over overwritable CodecParam parameters + pSCP->bVerbose = cSCP.bVerbose; + pSCP->cbStream = cSCP.cbStream; + pSCP->pWStream = cSCP.pWStream; + if(pSCP->uAlphaMode > 1) // something + alpha + pSCP->uAlphaMode = cSCP.uAlphaMode; // something + alpha to alpha or something transcoding! + + // validate color transcoding + if(pSCP->cfColorFormat == NCOMPONENT) + pII->cfColorFormat = NCOMPONENT; + if(pSCP->cfColorFormat == CMYK && pII->cfColorFormat != Y_ONLY && pII->cfColorFormat != CF_RGB) + pII->cfColorFormat = CMYK; + if(pSCP->cfColorFormat == YUV_422 && pII->cfColorFormat == YUV_420) + pII->cfColorFormat = YUV_422; + if(pSCP->cfColorFormat == YUV_444 && (pII->cfColorFormat == YUV_422 || pII->cfColorFormat == YUV_420)) + pII->cfColorFormat = YUV_444; + if(cII.cfColorFormat == CF_RGB && pII->cfColorFormat != Y_ONLY && + pII->cfColorFormat != NCOMPONENT) // no guarantee that number of channels will be >= 3 + pII->cfColorFormat = cII.cfColorFormat; + if(cII.cfColorFormat == CF_RGBE) + pII->cfColorFormat = CF_RGBE; + + // validate thumbnail parameters + if(pII->cThumbnailWidth == 0 || pII->cThumbnailWidth > pII->cWidth) + pII->cThumbnailWidth = pII->cWidth; + if(pII->cThumbnailHeight == 0 || pII->cThumbnailHeight > pII->cHeight) + pII->cThumbnailHeight = pII->cHeight; + if((pII->cWidth + pII->cThumbnailWidth - 1) / pII->cThumbnailWidth != (pII->cHeight + pII->cThumbnailHeight - 1) / pII->cThumbnailHeight) { + while((pII->cWidth + cScale - 1) / cScale > pII->cThumbnailWidth && + (pII->cHeight + cScale - 1) / cScale > pII->cThumbnailHeight && (cScale << 1)) + cScale <<= 1; + } + else { + cScale = (pII->cWidth + pII->cThumbnailWidth - 1) / pII->cThumbnailWidth; + if (cScale == 0) + cScale = 1; + } + pII->cThumbnailWidth = (pII->cWidth + cScale - 1) / cScale; + pII->cThumbnailHeight = (pII->cHeight + cScale - 1) / cScale; + + // validate region decode parameters + if(pII->cROIHeight == 0 || pII->cROIWidth == 0){ + pII->cROILeftX = pII->cROITopY = 0; + pII->cROIWidth = pII->cThumbnailWidth; + pII->cROIHeight = pII->cThumbnailHeight; + } + if(pII->cROILeftX >= pII->cThumbnailWidth) + pII->cROILeftX = 0; + if(pII->cROITopY >= pII->cThumbnailHeight) + pII->cROITopY = 0; + if(pII->cROILeftX + pII->cROIWidth > pII->cThumbnailWidth) + pII->cROIWidth = pII->cThumbnailWidth - pII->cROILeftX; + if(pII->cROITopY + pII->cROIHeight > pII->cThumbnailHeight) + pII->cROIHeight = pII->cThumbnailHeight - pII->cROITopY; + + return ICERR_OK; +} + +/************************************************************************* + Initialization of CWMImageStrCodec struct +*************************************************************************/ +static Void InitializeStrDec(CWMImageStrCodec *pSC, + const CCoreParameters *pParams, const CWMImageStrCodec *pSCIn) +{ + // copy core parameters + memcpy (&(pSC->m_param), pParams, sizeof (CCoreParameters)); + + pSC->cbStruct = sizeof(*pSC); + pSC->WMII = pSCIn->WMII; + pSC->WMISCP = pSCIn->WMISCP; + + pSC->cRow = 0; + pSC->cColumn = 0; + + pSC->cmbWidth = (pSC->WMII.cWidth + 15) / 16; + pSC->cmbHeight = (pSC->WMII.cHeight + 15) / 16; + + pSC->Load = outputMBRow; // output decoding result (ICC, etc) + pSC->Transform = pParams->cSubVersion == CODEC_SUBVERSION ? + invTransformMacroblock : invTransformMacroblock_alteredOperators_hard; + pSC->TransformCenter = pSC->Transform; + + pSC->ProcessTopLeft = processMacroblockDec; + pSC->ProcessTop = processMacroblockDec; + pSC->ProcessTopRight = processMacroblockDec; + pSC->ProcessLeft = processMacroblockDec; + pSC->ProcessCenter = processMacroblockDec; + pSC->ProcessRight = processMacroblockDec; + pSC->ProcessBottomLeft = processMacroblockDec; + pSC->ProcessBottom = processMacroblockDec; + pSC->ProcessBottomRight = processMacroblockDec; + + pSC->m_pNextSC = NULL; + pSC->m_bSecondary = FALSE; +} + +/************************************************************************* + ImageStrDecInit +*************************************************************************/ +Int ImageStrDecInit( + CWMImageInfo* pII, + CWMIStrCodecParam *pSCP, + CTXSTRCODEC* pctxSC) +{ + static size_t cbChannels[BD_MAX] = {2, 4}; + ERR err = WMP_errSuccess; + + size_t cbChannel = 0, cblkChroma = 0; + size_t cbMacBlockStride = 0, cbMacBlockChroma = 0, cMacBlock = 0; + + CWMImageStrCodec SC = {0}; + CWMImageStrCodec *pSC = NULL, *pNextSC = NULL; + char* pb = NULL; + size_t cb = 0, i; + Bool bLossyTranscoding = FALSE; + Bool bUseHardTileBoundaries = FALSE; //default is soft tile boundaries + Bool bLessThan64Bit = sizeof(void *) < 8; + + *pctxSC = NULL; + + if(WMPhotoValidate(pII, pSCP) != ICERR_OK) + return ICERR_ERROR; + + if(pSCP->sbSubband == SB_ISOLATED) // can not do anything with isolated bitstream + return ICERR_ERROR; + + //================================================ + SC.WMISCP.pWStream = pSCP->pWStream; + if (ReadWMIHeader(&SC.WMII, &SC.WMISCP, &SC.m_param) != ICERR_OK) { + return ICERR_ERROR; + } + + bUseHardTileBoundaries = SC.WMISCP.bUseHardTileBoundaries; + if(SC.WMII.cfColorFormat == CMYK && pII->cfColorFormat == CF_RGB) + bLossyTranscoding = TRUE; + if(pSCP->cfColorFormat != CMYK && (pII->cfColorFormat == CMYK)) + return ICERR_ERROR; + + //================================================ + SC.WMISCP = *pSCP; + SC.WMII = *pII; + + // original image size + SC.WMII.cWidth += SC.m_param.cExtraPixelsLeft + SC.m_param.cExtraPixelsRight; + SC.WMII.cHeight += SC.m_param.cExtraPixelsTop + SC.m_param.cExtraPixelsBottom; + pII->cROILeftX += SC.m_param.cExtraPixelsLeft; + pII->cROITopY += SC.m_param.cExtraPixelsTop; + + //================================================ + cbChannel = cbChannels[SC.WMISCP.bdBitDepth]; + cblkChroma = cblkChromas[SC.m_param.cfColorFormat]; + + cbMacBlockStride = cbChannel * 16 * 16; + cbMacBlockChroma = cbChannel * 16 * cblkChroma; + cMacBlock = (SC.WMII.cWidth + 15) / 16; + + //================================================ + cb = sizeof(*pSC) + (128 - 1) + sizeof(CWMDecoderParameters); + cb += (PACKETLENGTH * 4 - 1) + (PACKETLENGTH * 2 ) + sizeof(*pSC->pIOHeader); + + i = (cbMacBlockStride + cbMacBlockChroma * (SC.m_param.cNumChannels - 1)) * 2; // i <= 2^15 + if (bLessThan64Bit && ((i * (cMacBlock >> 16)) & 0xffffc000)) { + /** potential overflow - 32 bit pointers insufficient to address cache **/ + return ICERR_ERROR; + } + cb += i * cMacBlock; + + pb = malloc(cb); + if(pb == NULL) + return WMP_errOutOfMemory; + memset(pb, 0, cb); + + //================================================ + pSC = (CWMImageStrCodec*)pb; pb += sizeof(*pSC); + if(pSC == NULL) + return ICERR_ERROR; + + // Set up perf timers + PERFTIMER_ONLY(pSC->m_fMeasurePerf = pSCP->fMeasurePerf); + PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEndToEndPerf); + PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEncDecPerf); + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf); + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + PERFTIMER_COPYSTARTTIME(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf, pSC->m_ptEndToEndPerf); + + pSC->m_Dparam = (CWMDecoderParameters*)pb; pb += sizeof(CWMDecoderParameters); + pSC->cbChannel = cbChannel; + //pSC->cNumChannels = SC.WMISCP.cChannel; + pSC->bUseHardTileBoundaries = bUseHardTileBoundaries; + + //================================================ + InitializeStrDec(pSC, &SC.m_param, &SC); + + //================================================ + // 2 Macro Row buffers for each channel + pb = ALIGNUP(pb, 128); + for (i = 0; i < pSC->m_param.cNumChannels; i++) { + pSC->a0MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth; + pSC->a1MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth; + cbMacBlockStride = cbMacBlockChroma; + } + + //================================================ + // lay 2 aligned IO buffers just below pIO struct + pb = (char*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2; + pSC->pIOHeader = (BitIOInfo*)pb; pb += sizeof(*pSC->pIOHeader); + + // if interleaved alpha is needed + if (pSC->m_param.bAlphaChannel) { + SimpleBitIO SB = {0}; + cbMacBlockStride = cbChannel * 16 * 16; + + // 1. allocate new pNextSC info + //================================================ + cb = sizeof(*pNextSC) + (128 - 1) + cbMacBlockStride * cMacBlock * 2; + // if primary image is safe to allocate, alpha channel is certainly safe + pb = malloc(cb); + if(pb == NULL) + return WMP_errOutOfMemory; + memset(pb, 0, cb); + //================================================ + pNextSC = (CWMImageStrCodec*)pb; pb += sizeof(*pNextSC); + + // read plane header of second image plane + Call(attach_SB(&SB, pSCP->pWStream)); + InitializeStrDec(pNextSC, &SC.m_param, &SC); + ReadImagePlaneHeader(&pNextSC->WMII, &pNextSC->WMISCP, &pNextSC->m_param, &SB); + detach_SB(&SB); + + // 2. initialize pNextSC + if(pNextSC == NULL) + return ICERR_ERROR; + pNextSC->m_Dparam = pSC->m_Dparam; + pNextSC->cbChannel = cbChannel; + //================================================ + + // 3. initialize arrays +// InitializeStrDec(pNextSC, &SC.m_param, &SC); + pNextSC->m_param.cfColorFormat = Y_ONLY; + pNextSC->m_param.cNumChannels = 1; + pNextSC->m_param.bAlphaChannel = TRUE; + //================================================ + + // 2 Macro Row buffers for each channel + pb = ALIGNUP(pb, 128); + pNextSC->a0MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth; + pNextSC->a1MBbuffer[0] = (PixelI*)pb; + //================================================ + pNextSC->pIOHeader = pSC->pIOHeader; + //================================================ + + // 4. link pSC->pNextSC = pNextSC + pNextSC->m_pNextSC = pSC; + pNextSC->m_bSecondary = TRUE; + + } + else + pSC->WMISCP.uAlphaMode = 0; + + //================================================ + FailIf((StrIODecInit(pSC) != ICERR_OK), WMP_errOutOfMemory); + FailIf((StrDecInit(pSC) != ICERR_OK), WMP_errOutOfMemory); + if (pNextSC) { + // 5. StrEncInit + FailIf((StrDecInit(pNextSC) != ICERR_OK), WMP_errOutOfMemory); + } + + pSC->m_pNextSC = pNextSC; + //================================================ + *pII = pSC->WMII; + *pSCP = pSC->WMISCP; + *pctxSC = (CTXSTRCODEC)pSC; + + if(pSC->WMII.cPostProcStrength){ + initPostProc(pSC->pPostProcInfo, pSC->cmbWidth, pSC->m_param.cNumChannels); + if (pSC->m_param.bAlphaChannel) + initPostProc(pNextSC->pPostProcInfo, pNextSC->cmbWidth, pNextSC->m_param.cNumChannels); + } + + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + +Cleanup: + return WMP_errSuccess == err ? ICERR_OK : ICERR_ERROR; +} + +Int ImageStrDecDecode( + CTXSTRCODEC ctxSC, + const CWMImageBufferInfo* pBI +#ifdef REENTRANT_MODE + , size_t *pcDecodedLines +#endif + ) +{ + CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC; + CWMImageStrCodec* pNextSC = pSC->m_pNextSC; + size_t cMBRow, k; + + ImageDataProc ProcessLeft, ProcessCenter, ProcessRight; + ImageDataProc Transform = NULL; + const size_t iChromaElements = (pSC->m_param.cfColorFormat == YUV_420) ? 8 * 8 + : ((pSC->m_param.cfColorFormat == YUV_422) ? 8 * 16 : 16 * 16); + + if (sizeof(*pSC) != pSC->cbStruct) + { + return ICERR_ERROR; + } + + //================================ + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + + pSC->WMIBI = *pBI; + +#ifdef REENTRANT_MODE + if (0 == pSC->WMIBI.uiFirstMBRow) + { + setROI(pSC); + if (pNextSC) { + pNextSC->WMIBI = pSC->WMIBI; + setROI(pNextSC); + } + } +#else + setROI(pSC); + if (pNextSC) { + pNextSC->WMIBI = pSC->WMIBI; + setROI(pNextSC); + } +#endif // REENTRANT_MODE + +// optimization flags can be defined only after ROI is set! +#if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_DEC) || defined(WMP_OPT_TRFM_DEC) + StrDecOpt(pSC); +#endif // OPT defined + + + + cMBRow = (pSC->m_Dparam->bDecodeFullFrame ? pSC->cmbHeight : ((pSC->m_Dparam->cROIBottomY + 16) >> 4)); + +#ifdef REENTRANT_MODE + if (0 == pSC->WMIBI.uiFirstMBRow) + { + if(initLookupTables(pSC) != ICERR_OK) + return ICERR_ERROR; + if (pNextSC && initLookupTables(pNextSC) != ICERR_OK) + return ICERR_ERROR; + } +#else + if(initLookupTables(pSC) != ICERR_OK) + return ICERR_ERROR; + if (pNextSC && initLookupTables(pNextSC) != ICERR_OK) + return ICERR_ERROR; +#endif // REENTRANT_MODE + +#ifndef REENTRANT_MODE + if(pSC->WMII.bdBitDepth == BD_1){ + size_t i; + + + for(i = 0; i < pSC->WMIBI.cLine; i ++) + memset(pSC->WMIBI.pv, 0, pSC->WMIBI.cbStride); + } +#endif + + //================================ + // top row +#ifdef REENTRANT_MODE +#else + pSC->cRow = 0; + ProcessLeft = pSC->ProcessTopLeft; + ProcessCenter = pSC->ProcessTop; + ProcessRight = pSC->ProcessTopRight; + Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ? + invTransformMacroblock : invTransformMacroblock_alteredOperators_hard; +#endif // REENTRANT_MODE + +#ifdef REENTRANT_MODE + for (pSC->cRow = pSC->WMIBI.uiFirstMBRow; pSC->cRow <= pSC->WMIBI.uiLastMBRow; pSC->cRow++) + { + // const COLORFORMAT cfExt = (pSC->m_param.cfColorFormat == Y_ONLY ? Y_ONLY : pSC->WMII.cfColorFormat); + + if (0 == pSC->cRow) + { + ProcessLeft = pSC->ProcessTopLeft; + ProcessCenter = pSC->ProcessTop; + ProcessRight = pSC->ProcessTopRight; + Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ? + invTransformMacroblock : invTransformMacroblock_alteredOperators_hard; + } + else if (cMBRow == pSC->cRow) + { + //================================ + // bottom row + ProcessLeft = pSC->ProcessBottomLeft; + ProcessCenter = pSC->ProcessBottom; + ProcessRight = pSC->ProcessBottomRight; + Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ? + invTransformMacroblock : invTransformMacroblock_alteredOperators_hard; + } + else { // middle rows + ProcessLeft = pSC->ProcessLeft; + ProcessCenter = pSC->ProcessCenter; + ProcessRight = pSC->ProcessRight; + Transform = pSC->TransformCenter; + } +#else + //================================ + // central rows + for(pSC->cRow = 0; pSC->cRow <= cMBRow; pSC->cRow++) + { +#endif // REENTRANT_MODE + pSC->cColumn = 0; + initMRPtr(pSC); + /** zero out the transform coefficients (pull this out to once per MB row) **/ + memset(pSC->p1MBbuffer[0], 0, sizeof(PixelI) * 16 * 16 * pSC->cmbWidth); + for (k = 1; k < pSC->m_param.cNumChannels; k++) { + memset(pSC->p1MBbuffer[k], 0, sizeof(PixelI) * iChromaElements * pSC->cmbWidth); + } + if (pSC->m_pNextSC != NULL) { // alpha channel + memset(pSC->m_pNextSC->p1MBbuffer[0], 0, sizeof(PixelI) * 16 * 16 * pSC->m_pNextSC->cmbWidth); + } + + if(ProcessLeft(pSC) != ICERR_OK) + return ICERR_ERROR; + advanceMRPtr(pSC); + + pSC->Transform = Transform; + for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn) + { + if(ProcessCenter(pSC) != ICERR_OK) + return ICERR_ERROR; + advanceMRPtr(pSC); + } + pSC->Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ? + invTransformMacroblock : invTransformMacroblock_alteredOperators_hard; + + if(ProcessRight(pSC) != ICERR_OK) + return ICERR_ERROR; + + if (pSC->cRow) { + if(pSC->m_Dparam->cThumbnailScale < 2 && (pSC->m_Dparam->bDecodeFullFrame || + ((pSC->cRow * 16 > pSC->m_Dparam->cROITopY) && (pSC->cRow * 16 <= pSC->m_Dparam->cROIBottomY + 16)))) { + if( pSC->Load(pSC) != ICERR_OK ) // bypass CC for thumbnail decode + return ICERR_ERROR; + } + + if(pSC->m_Dparam->cThumbnailScale >= 2) // decode thumbnail + decodeThumbnail(pSC); + } + + advanceOneMBRow(pSC); + swapMRPtr(pSC); +#ifdef REENTRANT_MODE + *pcDecodedLines = pSC->WMIBI.cLinesDecoded; +#else + if (pSC->cRow == cMBRow - 1) { + //================================ + // bottom row + ProcessLeft = pSC->ProcessBottomLeft; + ProcessCenter = pSC->ProcessBottom; + ProcessRight = pSC->ProcessBottomRight; + Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ? + invTransformMacroblock : invTransformMacroblock_alteredOperators_hard; + } + else { + ProcessLeft = pSC->ProcessLeft; + ProcessCenter = pSC->ProcessCenter; + ProcessRight = pSC->ProcessRight; + Transform = pSC->TransformCenter; + } +#endif // REENTRANT_MODE + } + +#ifndef REENTRANT_MODE + fixup_Y_ONLY_to_Others(pSC, pBI); +#endif // REENTRANT_MODE + + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + return ICERR_OK; +} + +Int ImageStrDecTerm( + CTXSTRCODEC ctxSC) +{ + CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC; + if (NULL == pSC) + { + return ICERR_OK; + } + if (sizeof(*pSC) != pSC->cbStruct) + { + return ICERR_ERROR; + } + + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + + StrDecTerm(pSC); + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + PERFTIMER_REPORT(pSC->m_fMeasurePerf, pSC); + PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf); + + free(pSC); + + return ICERR_OK; +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec.o new file mode 100644 index 0000000..2a4de1b Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec_x86.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec_x86.c new file mode 100644 index 0000000..b9fc5ff --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/decode/strdec_x86.c @@ -0,0 +1,1640 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include "strcodec.h" +#include "decode.h" + +#if defined(WMP_OPT_SSE2) +#include +#include + +//================================================================ +static __m128i g_const_d0; +static __m128i g_const_d1; + +__m128i g_const_d3; +__m128i g_const_d4; +__m128i g_const_d0x80; +__m128i g_const_w0x80; +__m128i g_const_b0x80; + +//================================================================ +#if defined(WMP_OPT_CC_DEC) +__declspec(naked) void __stdcall storeRGB24_5( + U8* pbYCoCg, + size_t cbYCoCg, + const U8* pbRGB, + size_t cbRGB, + size_t cmb) +{ +#define DISP 8 + UNREFERENCED_PARAMETER( pbYCoCg ); + UNREFERENCED_PARAMETER( cbYCoCg ); + UNREFERENCED_PARAMETER( pbRGB ); + UNREFERENCED_PARAMETER( cbRGB ); + UNREFERENCED_PARAMETER( cmb ); + __asm { + push ebp + push ebx + push esi + push edi + + mov ebx, [esp + 36] // $ebx = cmb + mov edi, [esp + 28] // $edi = pbRGB + lea ebx, [ebx + ebx * 2] // $ebx = cmb * 3 + mov edx, [esp + 32] // $edx = cbRGB + shl ebx, 4 // $ebx = cmb * 3 * 16 + mov esi, [esp + 20] // $esi = pbYCoCg + add edi, ebx // $edi = pbRGB + 3 * 16 * cmb + mov ebp, [esp + 24] // $ebp = cbYCoCg + neg ebx + + mov eax, esp + and esp, 0xffffff80 + sub esp, 64 * 4 + DISP + + mov [esp], eax // original $esp + mov [esp + 4], edi + } +Loop0: + __asm { + mov edi, [esp + 4] // $edi = pbRGB + 3 * 16 * cmb + + // first 8 pixels + pxor xmm1, xmm1 + pxor xmm5, xmm5 + movdqa xmm0, [esi] + movdqa xmm4, [esi + 16] + psubd xmm1, [esi + ebp] + psubd xmm5, [esi + ebp + 16] + movdqa xmm2, [esi + ebp * 2] + movdqa xmm6, [esi + ebp * 2 + 16] + + paddd xmm0, [g_const_d0x80] + paddd xmm4, [g_const_d0x80] + + // ICC + movdqa xmm3, xmm1 // g -= r >> 1 + movdqa xmm7, xmm5 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm0, xmm3 + psubd xmm4, xmm7 + + movdqa xmm3, [g_const_d1] // r -= ((b + 1) >> 1) - g + movdqa xmm7, [g_const_d1] + paddd xmm3, xmm2 + paddd xmm7, xmm6 + paddd xmm1, xmm0 + paddd xmm5, xmm4 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + paddd xmm2, xmm1 // b += r + paddd xmm6, xmm5 + + pslld xmm0, 8 + pslld xmm2, 16 + pslld xmm4, 8 + pslld xmm6, 16 + por xmm0, xmm1 + por xmm4, xmm5 + por xmm0, xmm2 + por xmm4, xmm6 + + movdqa [esp + DISP + 64 * 0 + 16 * 0], xmm0 + pslld xmm0, 8 + movdqa [esp + DISP + 64 * 0 + 16 * 1], xmm4 + pslld xmm4, 8 + movdqa [esp + DISP + 64 * 0 + 16 * 2], xmm0 + movdqa [esp + DISP + 64 * 0 + 16 * 3], xmm4 + + // second 8 pixels + pxor xmm1, xmm1 + pxor xmm5, xmm5 + movdqa xmm0, [esi + 32] + movdqa xmm4, [esi + 48] + psubd xmm1, [esi + ebp + 32] + psubd xmm5, [esi + ebp + 48] + movdqa xmm2, [esi + ebp * 2 + 32] + movdqa xmm6, [esi + ebp * 2 + 48] + + paddd xmm0, [g_const_d0x80] + paddd xmm4, [g_const_d0x80] + + // ICC + movdqa xmm3, xmm1 // g -= r >> 1 + movdqa xmm7, xmm5 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm0, xmm3 + psubd xmm4, xmm7 + + movdqa xmm3, [g_const_d1] // r -= ((b + 1) >> 1) - g + movdqa xmm7, [g_const_d1] + paddd xmm3, xmm2 + paddd xmm7, xmm6 + paddd xmm1, xmm0 + paddd xmm5, xmm4 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + paddd xmm2, xmm1 // b += r + paddd xmm6, xmm5 + + pslld xmm0, 8 + pslld xmm2, 16 + pslld xmm4, 8 + pslld xmm6, 16 + por xmm0, xmm1 + por xmm4, xmm5 + por xmm0, xmm2 + por xmm4, xmm6 + + movdqa [esp + DISP + 64 * 1 + 16 * 0], xmm0 + pslld xmm0, 8 + movdqa [esp + DISP + 64 * 1 + 16 * 1], xmm4 + pslld xmm4, 8 + movdqa [esp + DISP + 64 * 1 + 16 * 2], xmm0 + movdqa [esp + DISP + 64 * 1 + 16 * 3], xmm4 + + //================ + add esi, 64 + + // first 8 pixels + pxor xmm1, xmm1 + pxor xmm5, xmm5 + movdqa xmm0, [esi] + movdqa xmm4, [esi + 16] + psubd xmm1, [esi + ebp] + psubd xmm5, [esi + ebp + 16] + movdqa xmm2, [esi + ebp * 2] + movdqa xmm6, [esi + ebp * 2 + 16] + + paddd xmm0, [g_const_d0x80] + paddd xmm4, [g_const_d0x80] + + // ICC + movdqa xmm3, xmm1 // g -= r >> 1 + movdqa xmm7, xmm5 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm0, xmm3 + psubd xmm4, xmm7 + + movdqa xmm3, [g_const_d1] // r -= ((b + 1) >> 1) - g + movdqa xmm7, [g_const_d1] + paddd xmm3, xmm2 + paddd xmm7, xmm6 + paddd xmm1, xmm0 + paddd xmm5, xmm4 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + paddd xmm2, xmm1 // b += r + paddd xmm6, xmm5 + + pslld xmm0, 8 + pslld xmm2, 16 + pslld xmm4, 8 + pslld xmm6, 16 + + por xmm0, xmm1 + por xmm4, xmm5 + por xmm0, xmm2 + por xmm4, xmm6 + + movdqa [esp + DISP + 64 * 2 + 16 * 0], xmm0 + pslld xmm0, 8 + movdqa [esp + DISP + 64 * 2 + 16 * 1], xmm4 + pslld xmm4, 8 + movdqa [esp + DISP + 64 * 2 + 16 * 2], xmm0 + movdqa [esp + DISP + 64 * 2 + 16 * 3], xmm4 + + // second 8 pixels + pxor xmm1, xmm1 + pxor xmm5, xmm5 + movdqa xmm0, [esi + 32] + movdqa xmm4, [esi + 48] + psubd xmm1, [esi + ebp + 32] + psubd xmm5, [esi + ebp + 48] + movdqa xmm2, [esi + ebp * 2 + 32] + movdqa xmm6, [esi + ebp * 2 + 48] + + paddd xmm0, [g_const_d0x80] + paddd xmm4, [g_const_d0x80] + + // ICC + movdqa xmm3, xmm1 // g -= r >> 1 + movdqa xmm7, xmm5 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm0, xmm3 + psubd xmm4, xmm7 + + movdqa xmm3, [g_const_d1] // r -= ((b + 1) >> 1) - g + movdqa xmm7, [g_const_d1] + paddd xmm3, xmm2 + paddd xmm7, xmm6 + paddd xmm1, xmm0 + paddd xmm5, xmm4 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + paddd xmm2, xmm1 // b += r + paddd xmm6, xmm5 + + pslld xmm0, 8 + pslld xmm2, 16 + pslld xmm4, 8 + pslld xmm6, 16 + por xmm0, xmm1 + por xmm4, xmm5 + por xmm0, xmm2 + por xmm4, xmm6 + + movdqa [esp + DISP + 64 * 3 + 16 * 0], xmm0 + pslld xmm0, 8 + movdqa [esp + DISP + 64 * 3 + 16 * 1], xmm4 + pslld xmm4, 8 + movdqa [esp + DISP + 64 * 3 + 16 * 2], xmm0 + movdqa [esp + DISP + 64 * 3 + 16 * 3], xmm4 + + //================================ + // RGBX32 -> RGB24 + mov eax, [esp + DISP + 64 * 0 + 4] // ..B1G1R1 + mov ecx, [esp + DISP + 64 * 0 + 32] // B0G0R0.. + shld eax, ecx, 24 // R1B0G0R0 + mov [edi + ebx + 0], eax + mov eax, [esp + DISP + 64 * 0 + 20] // ..B5G5R5 + mov ecx, [esp + DISP + 64 * 0 + 36] // B1G1R1.. + shld eax, ecx, 16 // G5R5B1G1 + mov [edi + ebx + 4], eax + mov eax, [esp + DISP + 64 * 0 + 16] // ..B4G4R4 + mov ecx, [esp + DISP + 64 * 0 + 52] // B5G5R5.. + shld eax, ecx, 8 // B4G4R4B5 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + mov eax, [esp + DISP + 64 * 0 + 4 + 8] // ..B3G3R3 + mov ecx, [esp + DISP + 64 * 0 + 32 + 8] // B2G2R2.. + shld eax, ecx, 24 // R3B2G2R2 + mov [edi + ebx + 0], eax + mov eax, [esp + DISP + 64 * 0 + 20 + 8] // ..B7G7R7 + mov ecx, [esp + DISP + 64 * 0 + 36 + 8] // B3G3R3.. + shld eax, ecx, 16 // G7R7B3G3 + mov [edi + ebx + 4], eax + mov eax, [esp + DISP + 64 * 0 + 16 + 8] // ..B6G6R6 + mov ecx, [esp + DISP + 64 * 0 + 52 + 8] // B7G7R7.. + shld eax, ecx, 8 // B6G6R6B7 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + // RGBX32 -> RGB24 + mov eax, [esp + DISP + 64 * 1 + 4 + 8] // ..B3G3R3 + mov ecx, [esp + DISP + 64 * 1 + 32 + 8] // B2G2R2.. + shld eax, ecx, 24 // R3B2G2R2 + mov [edi + ebx + 0], eax + mov eax, [esp + DISP + 64 * 1 + 20 + 8] // ..B7G7R7 + mov ecx, [esp + DISP + 64 * 1 + 36 + 8] // B3G3R3.. + shld eax, ecx, 16 // G7R7B3G3 + mov [edi + ebx + 4], eax + mov eax, [esp + DISP + 64 * 1 + 16 + 8] // ..B6G6R6 + mov ecx, [esp + DISP + 64 * 1 + 52 + 8] // B7G7R7.. + shld eax, ecx, 8 // B6G6R6B7 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + mov eax, [esp + DISP + 64 * 1 + 4] // ..B1G1R1 + mov ecx, [esp + DISP + 64 * 1 + 32] // B0G0R0.. + shld eax, ecx, 24 // R1B0G0R0 + mov [edi + ebx + 0], eax + mov eax, [esp + DISP + 64 * 1 + 20] // ..B5G5R5 + mov ecx, [esp + DISP + 64 * 1 + 36] // B1G1R1.. + shld eax, ecx, 16 // G5R5B1G1 + mov [edi + ebx + 4], eax + mov eax, [esp + DISP + 64 * 1 + 16] // ..B4G4R4 + mov ecx, [esp + DISP + 64 * 1 + 52] // B5G5R5.. + shld eax, ecx, 8 // B4G4R4B5 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + // RGBX32 -> RGB24 + mov eax, [esp + DISP + 64 * 2 + 4] // ..B1G1R1 + mov ecx, [esp + DISP + 64 * 2 + 32] // B0G0R0.. + shld eax, ecx, 24 // R1B0G0R0 + mov [edi + ebx + 0], eax + mov eax, [esp + DISP + 64 * 2 + 20] // ..B5G5R5 + mov ecx, [esp + DISP + 64 * 2 + 36] // B1G1R1.. + shld eax, ecx, 16 // G5R5B1G1 + mov [edi + ebx + 4], eax + mov eax, [esp + DISP + 64 * 2 + 16] // ..B4G4R4 + mov ecx, [esp + DISP + 64 * 2 + 52] // B5G5R5.. + shld eax, ecx, 8 // B4G4R4B5 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + mov eax, [esp + DISP + 64 * 2 + 4 + 8] // ..B3G3R3 + mov ecx, [esp + DISP + 64 * 2 + 32 + 8] // B2G2R2.. + shld eax, ecx, 24 // R3B2G2R2 + mov [edi + ebx + 0], eax + mov eax, [esp + DISP + 64 * 2 + 20 + 8] // ..B7G7R7 + mov ecx, [esp + DISP + 64 * 2 + 36 + 8] // B3G3R3.. + shld eax, ecx, 16 // G7R7B3G3 + mov [edi + ebx + 4], eax + mov eax, [esp + DISP + 64 * 2 + 16 + 8] // ..B6G6R6 + mov ecx, [esp + DISP + 64 * 2 + 52 + 8] // B7G7R7.. + shld eax, ecx, 8 // B6G6R6B7 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + // RGBX32 -> RGB24 + mov eax, [esp + DISP + 64 * 3 + 4 + 8] // ..B3G3R3 + mov ecx, [esp + DISP + 64 * 3 + 32 + 8] // B2G2R2.. + shld eax, ecx, 24 // R3B2G2R2 + mov [edi + ebx + 0], eax + mov eax, [esp + DISP + 64 * 3 + 20 + 8] // ..B7G7R7 + mov ecx, [esp + DISP + 64 * 3 + 36 + 8] // B3G3R3.. + shld eax, ecx, 16 // G7R7B3G3 + mov [edi + ebx + 4], eax + mov eax, [esp + DISP + 64 * 3 + 16 + 8] // ..B6G6R6 + mov ecx, [esp + DISP + 64 * 3 + 52 + 8] // B7G7R7.. + shld eax, ecx, 8 // B6G6R6B7 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + mov eax, [esp + DISP + 64 * 3 + 4] // ..B1G1R1 + mov ecx, [esp + DISP + 64 * 3 + 32] // B0G0R0.. + shld eax, ecx, 24 // R1B0G0R0 + mov [edi + ebx + 0], eax + mov eax, [esp + DISP + 64 * 3 + 20] // ..B5G5R5 + mov ecx, [esp + DISP + 64 * 3 + 36] // B1G1R1.. + shld eax, ecx, 16 // G5R5B1G1 + mov [edi + ebx + 4], eax + mov eax, [esp + DISP + 64 * 3 + 16] // ..B4G4R4 + mov ecx, [esp + DISP + 64 * 3 + 52] // B5G5R5.. + shld eax, ecx, 8 // B4G4R4B5 + mov [edi + ebx + 8], eax + + //================================ + add esi, 256 - 64 + add ebx, 12 + jnz Loop0 + + //================ + pop esp + pop edi + pop esi + pop ebx + pop ebp + ret 20 + } +} + +Int outputMBRow_RGB24_Lossless_1(CWMImageStrCodec* pSC) +{ +#ifdef REENTRANT_MODE + const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16); + const size_t iFirstRow = ((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)); +#endif + const size_t cbRGB = pSC->WMIBI.cbStride; + const U8* const pbRGB = (U8*)pSC->WMIBI.pv + cbRGB * (pSC->cRow - 1) * 16; + + U8* const pbY = (U8*)pSC->a0MBbuffer[0]; + U8* const pbU = (U8*)pSC->a0MBbuffer[1]; + // U8* const pbV = (U8*)pSC->a0MBbuffer[2]; + + const size_t cmbColumn = (pSC->WMII.cWidth + 15) / 16; + + assert(BD_8 == pSC->WMII.bdBitDepth); + assert(CF_RGB == pSC->WMII.cfColorFormat); + assert(24 == pSC->WMII.cBitsPerUnit); + assert(pSC->WMII.bRGB); + assert(O_NONE == pSC->WMII.oOrientation); + + assert(YUV_444 == pSC->m_param.cfColorFormat); + assert(!pSC->m_param.bScaledArith); + + assert(pSC->m_Dparam->bDecodeFullFrame); + + storeRGB24_5(pbY + 64 * 0, pbU - pbY, pbRGB + cbRGB * 0, cbRGB, cmbColumn); + storeRGB24_5(pbY + 64 * 2, pbU - pbY, pbRGB + cbRGB * 8, cbRGB, cmbColumn); + +#ifdef REENTRANT_MODE + pSC->WMIBI.cLinesDecoded = cHeight - iFirstRow; +#endif + return ICERR_OK; +} + + +__declspec(naked) void __stdcall storeRGB24_3( + U8* pbYCoCg, + size_t cbYCoCg, + const U8* pbRGB, + size_t cbRGB, + size_t cmb, + const U8* Shift) +{ + UNREFERENCED_PARAMETER( pbYCoCg ); + UNREFERENCED_PARAMETER( cbYCoCg ); + UNREFERENCED_PARAMETER( pbRGB ); + UNREFERENCED_PARAMETER( cbRGB ); + UNREFERENCED_PARAMETER( cmb ); + UNREFERENCED_PARAMETER( Shift ); + __asm { + push ebp + push ebx + push esi + push edi + + mov ecx, [esp + 40] // $ecx = Shift + mov ebx, [esp + 36] // $ebx = cmb + mov edi, [esp + 28] // $edi = pbRGB + lea ebx, [ebx + ebx * 2] // $ebx = cmb * 3 + mov edx, [esp + 32] // $edx = cbRGB + shl ebx, 4 // $ebx = cmb * 3 * 16 + mov esi, [esp + 20] // $esi = pbYCoCg + add edi, ebx // $edi = pbRGB + 3 * 16 * cmb + mov ebp, [esp + 24] // $ebp = cbYCoCg + neg ebx + + mov eax, esp + and esp, 0xffffff80 + sub esp, 320 + + mov [esp], eax // original $esp + mov [esp + 4], edi + mov [esp + 8], ecx + } +Loop0: + __asm { + mov edi, [esp + 4] // $edi = pbRGB + 3 * 16 * cmb + + //================ + // first 8 pixels + movdqa xmm0, [esi] + movdqa xmm4, [esi + 16] + movdqa xmm3, [esi + ebp] + movdqa xmm7, [esi + ebp + 16] + movdqa xmm2, [esi + ebp * 2] + movdqa xmm6, [esi + ebp * 2 + 16] + + mov ecx, [esp + 8] + movdqa xmm1, [ecx] + movdqa xmm5, [g_const_d0x80] + pslld xmm5, xmm1 + paddd xmm5, xmm1 + paddd xmm0, xmm5 // bias + paddd xmm4, xmm5 // bias + pxor xmm1, xmm1 + pxor xmm5, xmm5 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + // ICC + movdqa xmm3, xmm1 // g -= r >> 1 + movdqa xmm7, xmm5 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm0, xmm3 + psubd xmm4, xmm7 + + movdqa xmm3, [g_const_d1] // r -= ((b + 1) >> 1) - g + movdqa xmm7, [g_const_d1] + paddd xmm3, xmm2 + paddd xmm7, xmm6 + paddd xmm1, xmm0 + paddd xmm5, xmm4 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + paddd xmm2, xmm1 // b += r + paddd xmm6, xmm5 + + // clip + movdqa xmm3, [g_const_w0x80] + packssdw xmm0, xmm4 + packssdw xmm1, xmm5 + packssdw xmm2, xmm6 + + mov ecx, [esp + 8] + movdqa xmm4, [ecx] + psraw xmm0, xmm4 + psraw xmm1, xmm4 + psraw xmm2, xmm4 + + psubw xmm0, xmm3 + psubw xmm1, xmm3 + psubw xmm2, xmm3 + + movdqa [esp + 16], xmm0 + movdqa [esp + 32], xmm1 + movdqa [esp + 48], xmm2 + + //================ + // second 8 pixels + movdqa xmm0, [esi + 32] + movdqa xmm4, [esi + 48] + movdqa xmm3, [esi + ebp + 32] + movdqa xmm7, [esi + ebp + 48] + movdqa xmm2, [esi + ebp * 2 + 32] + movdqa xmm6, [esi + ebp * 2 + 48] + + mov ecx, [esp + 8] + movdqa xmm1, [ecx] + movdqa xmm5, [g_const_d0x80] + pslld xmm5, xmm1 + paddd xmm5, xmm1 + paddd xmm0, xmm5 // bias + paddd xmm4, xmm5 // bias + pxor xmm1, xmm1 + pxor xmm5, xmm5 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + // ICC + movdqa xmm3, xmm1 // g -= r >> 1 + movdqa xmm7, xmm5 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm0, xmm3 + psubd xmm4, xmm7 + + movdqa xmm3, [g_const_d1] // r -= ((b + 1) >> 1) - g + movdqa xmm7, [g_const_d1] + paddd xmm3, xmm2 + paddd xmm7, xmm6 + paddd xmm1, xmm0 + paddd xmm5, xmm4 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + paddd xmm2, xmm1 // b += r + paddd xmm6, xmm5 + + // clip + movdqa xmm3, [g_const_w0x80] + packssdw xmm0, xmm4 + packssdw xmm1, xmm5 + packssdw xmm2, xmm6 + + mov ecx, [esp + 8] + movdqa xmm4, [ecx] + psraw xmm0, xmm4 + psraw xmm1, xmm4 + psraw xmm2, xmm4 + + psubw xmm0, xmm3 + psubw xmm1, xmm3 + psubw xmm2, xmm3 + + //================ + // 16 pixels + movdqa xmm3, [g_const_b0x80] + packsswb xmm0, [esp + 16] + packsswb xmm1, [esp + 32] + packsswb xmm2, [esp + 48] + + psubb xmm0, xmm3 + psubb xmm1, xmm3 + psubb xmm2, xmm3 + + pxor xmm7, xmm7 + movdqa xmm4, xmm0 + movdqa xmm5, xmm1 + movdqa xmm6, xmm2 + + punpckhbw xmm0, xmm7 + punpckhbw xmm1, xmm7 + punpckhbw xmm2, xmm7 + punpcklbw xmm4, xmm7 + punpcklbw xmm5, xmm7 + punpcklbw xmm6, xmm7 + + // spill second 8 pixels + movdqa [esp + 16], xmm4 + movdqa [esp + 32], xmm5 + movdqa [esp + 48], xmm6 + + // first 8 pixels + movdqa xmm4, xmm0 + movdqa xmm5, xmm1 + movdqa xmm6, xmm2 + + punpcklwd xmm0, xmm7 + punpcklwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + + punpckhwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + punpckhwd xmm6, xmm7 + + pslld xmm0, 8 + pslld xmm2, 16 + pslld xmm4, 8 + pslld xmm6, 16 + + por xmm0, xmm1 + por xmm4, xmm5 + por xmm0, xmm2 + por xmm4, xmm6 + + movdqa [esp + 64], xmm0 + pslld xmm0, 8 + movdqa [esp + 80], xmm4 + pslld xmm4, 8 + movdqa [esp + 96], xmm0 + movdqa [esp + 112], xmm4 + + // second 8 pixels + movdqa xmm0, [esp + 16] + movdqa xmm1, [esp + 32] + movdqa xmm2, [esp + 48] + movdqa xmm4, xmm0 + movdqa xmm5, xmm1 + movdqa xmm6, xmm2 + + punpcklwd xmm0, xmm7 + punpcklwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + punpckhwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + punpckhwd xmm6, xmm7 + + pslld xmm0, 8 + pslld xmm2, 16 + pslld xmm4, 8 + pslld xmm6, 16 + por xmm0, xmm1 + por xmm4, xmm5 + por xmm0, xmm2 + por xmm4, xmm6 + + movdqa [esp + 128], xmm0 + pslld xmm0, 8 + movdqa [esp + 144], xmm4 + pslld xmm4, 8 + movdqa [esp + 160], xmm0 + movdqa [esp + 176], xmm4 + + //================================ + add esi, 64 + + //================ + // first 8 pixels + movdqa xmm0, [esi] + movdqa xmm4, [esi + 16] + movdqa xmm3, [esi + ebp] + movdqa xmm7, [esi + ebp + 16] + movdqa xmm2, [esi + ebp * 2] + movdqa xmm6, [esi + ebp * 2 + 16] + + mov ecx, [esp + 8] + movdqa xmm1, [ecx] + movdqa xmm5, [g_const_d0x80] + pslld xmm5, xmm1 + paddd xmm5, xmm1 + paddd xmm0, xmm5 // bias + paddd xmm4, xmm5 // bias + pxor xmm1, xmm1 + pxor xmm5, xmm5 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + // ICC + movdqa xmm3, xmm1 // g -= r >> 1 + movdqa xmm7, xmm5 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm0, xmm3 + psubd xmm4, xmm7 + + movdqa xmm3, [g_const_d1] // r -= ((b + 1) >> 1) - g + movdqa xmm7, [g_const_d1] + paddd xmm3, xmm2 + paddd xmm7, xmm6 + paddd xmm1, xmm0 + paddd xmm5, xmm4 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + paddd xmm2, xmm1 // b += r + paddd xmm6, xmm5 + + // clip + movdqa xmm3, [g_const_w0x80] + packssdw xmm0, xmm4 + packssdw xmm1, xmm5 + packssdw xmm2, xmm6 + + mov ecx, [esp + 8] + movdqa xmm4, [ecx] + psraw xmm0, xmm4 + psraw xmm1, xmm4 + psraw xmm2, xmm4 + + psubw xmm0, xmm3 + psubw xmm1, xmm3 + psubw xmm2, xmm3 + + movdqa [esp + 16], xmm0 + movdqa [esp + 32], xmm1 + movdqa [esp + 48], xmm2 + + //================ + // second 8 pixels + movdqa xmm0, [esi + 32] + movdqa xmm4, [esi + 48] + movdqa xmm3, [esi + ebp + 32] + movdqa xmm7, [esi + ebp + 48] + movdqa xmm2, [esi + ebp * 2 + 32] + movdqa xmm6, [esi + ebp * 2 + 48] + + mov ecx, [esp + 8] + movdqa xmm1, [ecx] + movdqa xmm5, [g_const_d0x80] + pslld xmm5, xmm1 + paddd xmm5, xmm1 + paddd xmm0, xmm5 // bias + paddd xmm4, xmm5 // bias + pxor xmm1, xmm1 + pxor xmm5, xmm5 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + // ICC + movdqa xmm3, xmm1 // g -= r >> 1 + movdqa xmm7, xmm5 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm0, xmm3 + psubd xmm4, xmm7 + + movdqa xmm3, [g_const_d1] // r -= ((b + 1) >> 1) - g + movdqa xmm7, [g_const_d1] + paddd xmm3, xmm2 + paddd xmm7, xmm6 + paddd xmm1, xmm0 + paddd xmm5, xmm4 + psrad xmm3, 1 + psrad xmm7, 1 + psubd xmm1, xmm3 + psubd xmm5, xmm7 + + paddd xmm2, xmm1 // b += r + paddd xmm6, xmm5 + + // clip + movdqa xmm3, [g_const_w0x80] + packssdw xmm0, xmm4 + packssdw xmm1, xmm5 + packssdw xmm2, xmm6 + + mov ecx, [esp + 8] + movdqa xmm4, [ecx] + psraw xmm0, xmm4 + psraw xmm1, xmm4 + psraw xmm2, xmm4 + + psubw xmm0, xmm3 + psubw xmm1, xmm3 + psubw xmm2, xmm3 + + //================ + // 16 pixels + movdqa xmm3, [g_const_b0x80] + packsswb xmm0, [esp + 16] + packsswb xmm1, [esp + 32] + packsswb xmm2, [esp + 48] + + psubb xmm0, xmm3 + psubb xmm1, xmm3 + psubb xmm2, xmm3 + + pxor xmm7, xmm7 + movdqa xmm4, xmm0 + movdqa xmm5, xmm1 + movdqa xmm6, xmm2 + + punpckhbw xmm0, xmm7 + punpckhbw xmm1, xmm7 + punpckhbw xmm2, xmm7 + punpcklbw xmm4, xmm7 + punpcklbw xmm5, xmm7 + punpcklbw xmm6, xmm7 + + // spill second 8 pixels + movdqa [esp + 16], xmm4 + movdqa [esp + 32], xmm5 + movdqa [esp + 48], xmm6 + + // first 8 pixels + movdqa xmm4, xmm0 + movdqa xmm5, xmm1 + movdqa xmm6, xmm2 + + punpcklwd xmm0, xmm7 + punpcklwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + + punpckhwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + punpckhwd xmm6, xmm7 + + pslld xmm0, 8 + pslld xmm2, 16 + pslld xmm4, 8 + pslld xmm6, 16 + + por xmm0, xmm1 + por xmm4, xmm5 + por xmm0, xmm2 + por xmm4, xmm6 + + movdqa [esp + 192], xmm0 + pslld xmm0, 8 + movdqa [esp + 208], xmm4 + pslld xmm4, 8 + movdqa [esp + 224], xmm0 + movdqa [esp + 240], xmm4 + + // second 8 pixels + movdqa xmm0, [esp + 16] + movdqa xmm1, [esp + 32] + movdqa xmm2, [esp + 48] + movdqa xmm4, xmm0 + movdqa xmm5, xmm1 + movdqa xmm6, xmm2 + + punpcklwd xmm0, xmm7 + punpcklwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + punpckhwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + punpckhwd xmm6, xmm7 + + pslld xmm0, 8 + pslld xmm2, 16 + pslld xmm4, 8 + pslld xmm6, 16 + por xmm0, xmm1 + por xmm4, xmm5 + por xmm0, xmm2 + por xmm4, xmm6 + + movdqa [esp + 256], xmm0 + pslld xmm0, 8 + movdqa [esp + 272], xmm4 + pslld xmm4, 8 + movdqa [esp + 288], xmm0 + movdqa [esp + 304], xmm4 + + // RGBX32 -> RGB24 + mov eax, [esp + 68] // ..B1G1R1 + mov ecx, [esp + 96] // B0G0R0.. + shld eax, ecx, 24 // R1B0G0R0 + mov [edi + ebx + 0], eax + mov eax, [esp + 84] // ..B5G5R5 + mov ecx, [esp + 100] // B1G1R1.. + shld eax, ecx, 16 // G5R5B1G1 + mov [edi + ebx + 4], eax + mov eax, [esp + 80] // ..B4G4R4 + mov ecx, [esp + 116] // B5G5R5.. + shld eax, ecx, 8 // B4G4R4B5 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + mov eax, [esp + 76] // ..B3G3R3 + mov ecx, [esp + 104] // B2G2R2.. + shld eax, ecx, 24 // R3B2G2R2 + mov [edi + ebx + 0], eax + mov eax, [esp + 92] // ..B7G7R7 + mov ecx, [esp + 108] // B3G3R3.. + shld eax, ecx, 16 // G7R7B3G3 + mov [edi + ebx + 4], eax + mov eax, [esp + 88] // ..B6G6R6 + mov ecx, [esp + 124] // B7G7R7.. + shld eax, ecx, 8 // B6G6R6B7 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + // RGBX32 -> RGB24 + mov eax, [esp + 140] // ..B3G3R3 + mov ecx, [esp + 168] // B2G2R2.. + shld eax, ecx, 24 // R3B2G2R2 + mov [edi + ebx + 0], eax + mov eax, [esp + 156] // ..B7G7R7 + mov ecx, [esp + 172] // B3G3R3.. + shld eax, ecx, 16 // G7R7B3G3 + mov [edi + ebx + 4], eax + mov eax, [esp + 152] // ..B6G6R6 + mov ecx, [esp + 188] // B7G7R7.. + shld eax, ecx, 8 // B6G6R6B7 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + mov eax, [esp + 132] // ..B1G1R1 + mov ecx, [esp + 160] // B0G0R0.. + shld eax, ecx, 24 // R1B0G0R0 + mov [edi + ebx + 0], eax + mov eax, [esp + 148] // ..B5G5R5 + mov ecx, [esp + 164] // B1G1R1.. + shld eax, ecx, 16 // G5R5B1G1 + mov [edi + ebx + 4], eax + mov eax, [esp + 144] // ..B4G4R4 + mov ecx, [esp + 180] // B5G5R5.. + shld eax, ecx, 8 // B4G4R4B5 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + // RGBX32 -> RGB24 + mov eax, [esp + 196] // ..B1G1R1 + mov ecx, [esp + 224] // B0G0R0.. + shld eax, ecx, 24 // R1B0G0R0 + mov [edi + ebx + 0], eax + mov eax, [esp + 212] // ..B5G5R5 + mov ecx, [esp + 228] // B1G1R1.. + shld eax, ecx, 16 // G5R5B1G1 + mov [edi + ebx + 4], eax + mov eax, [esp + 208] // ..B4G4R4 + mov ecx, [esp + 244] // B5G5R5.. + shld eax, ecx, 8 // B4G4R4B5 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + mov eax, [esp + 204] // ..B3G3R3 + mov ecx, [esp + 232] // B2G2R2.. + shld eax, ecx, 24 // R3B2G2R2 + mov [edi + ebx + 0], eax + mov eax, [esp + 220] // ..B7G7R7 + mov ecx, [esp + 236] // B3G3R3.. + shld eax, ecx, 16 // G7R7B3G3 + mov [edi + ebx + 4], eax + mov eax, [esp + 216] // ..B6G6R6 + mov ecx, [esp + 252] // B7G7R7.. + shld eax, ecx, 8 // B6G6R6B7 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + // RGBX32 -> RGB24 + mov eax, [esp + 268] // ..B3G3R3 + mov ecx, [esp + 296] // B2G2R2.. + shld eax, ecx, 24 // R3B2G2R2 + mov [edi + ebx + 0], eax + mov eax, [esp + 284] // ..B7G7R7 + mov ecx, [esp + 300] // B3G3R3.. + shld eax, ecx, 16 // G7R7B3G3 + mov [edi + ebx + 4], eax + mov eax, [esp + 280] // ..B6G6R6 + mov ecx, [esp + 316] // B7G7R7.. + shld eax, ecx, 8 // B6G6R6B7 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + mov eax, [esp + 260] // ..B1G1R1 + mov ecx, [esp + 288] // B0G0R0.. + shld eax, ecx, 24 // R1B0G0R0 + mov [edi + ebx + 0], eax + mov eax, [esp + 276] // ..B5G5R5 + mov ecx, [esp + 292] // B1G1R1.. + shld eax, ecx, 16 // G5R5B1G1 + mov [edi + ebx + 4], eax + mov eax, [esp + 272] // ..B4G4R4 + mov ecx, [esp + 308] // B5G5R5.. + shld eax, ecx, 8 // B4G4R4B5 + mov [edi + ebx + 8], eax + add edi, edx // $edi = pbRGB += cbRGB + + //================================ + add esi, 256 - 64 + add ebx, 12 + jnz Loop0 + + //================ + pop esp + pop edi + pop esi + pop ebx + pop ebp + ret 24 + } +} + +Int outputMBRow_RGB24_Lossy_3(CWMImageStrCodec* pSC) +{ +#ifdef REENTRANT_MODE + const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16); + const size_t iFirstRow = ((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)); +#endif + const size_t cbRGB = pSC->WMIBI.cbStride; + const U8* const pbRGB = (U8*)pSC->WMIBI.pv + cbRGB * (pSC->cRow - 1) * 16; + + U8* const pbY = (U8*)pSC->a0MBbuffer[0]; + U8* const pbU = (U8*)pSC->a0MBbuffer[1]; + // U8* const pbV = (U8*)pSC->a0MBbuffer[2]; + + const size_t cmbColumn = (pSC->WMII.cWidth + 15) / 16; + + __declspec(align(16)) U8 Shift[16]; + + assert(BD_8 == pSC->WMII.bdBitDepth); + assert(CF_RGB == pSC->WMII.cfColorFormat); + assert(24 == pSC->WMII.cBitsPerUnit); + assert(pSC->WMII.bRGB); + assert(O_NONE == pSC->WMII.oOrientation); + + assert(YUV_444 == pSC->m_param.cfColorFormat); + + assert(pSC->m_Dparam->bDecodeFullFrame); + + _mm_store_si128((__m128i *) Shift, pSC->m_param.bScaledArith ? g_const_d3 : g_const_d0); + storeRGB24_3(pbY + 64 * 0, pbU - pbY, pbRGB + cbRGB * 0, cbRGB, cmbColumn, + Shift); + storeRGB24_3(pbY + 64 * 2, pbU - pbY, pbRGB + cbRGB * 8, cbRGB, cmbColumn, + Shift); + +#ifdef REENTRANT_MODE + pSC->WMIBI.cLinesDecoded = cHeight - iFirstRow; +#endif + return ICERR_OK; +} +#endif + +//================================================================ +#if defined(WMP_OPT_TRFM_DEC) +FORCE_INLINE Void strDCT2x2up_OPT(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, C, t; + a = *pa; + b = *pb; + C = *pc; + d = *pd; + + a += d; + b -= C; + t = ((a - b + 1) >> 1); + c = t - d; + d = t - C; + a -= d; + b += c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +FORCE_INLINE Void invOdd_OPT(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + b += d; + a -= c; + d -= (b) >> 1; + c += (a + 1) >> 1; + + /** rotate pi/8 **/ +#define IROTATE2(a, b) (a) -= (((b)*3 + 4) >> 3), (b) += (((a)*3 + 4) >> 3) + IROTATE2(a, b); + IROTATE2(c, d); + + /** butterflies **/ + c -= (b + 1) >> 1; + d = ((a + 1) >> 1) - d; + b += c; + a -= d; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +FORCE_INLINE Void invOddOdd_OPT(PixelI* pa, PixelI* pb, PixelI* pc, PixelI* pd) +{ + PixelI a, b, c, d, t1, t2; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + d += a; + c -= b; + a -= (t1 = d >> 1); + b += (t2 = c >> 1); + + /** rotate pi/4 **/ + a -= (b * 3 + 3) >> 3; + b += (a * 3 + 3) >> 2; + a -= (b * 3 + 4) >> 3; + + /** butterflies **/ + b -= t2; + a += t1; + c += b; + d -= a; + + /** sign flips **/ + *pa = a; + *pb = -b; + *pc = -c; + *pd = d; +} + +FORCE_INLINE Void strDCT2x2dn_SSE2_1(PixelI* p) +{ + __m128i* const pdq = (__m128i*)p; + __m128i a = pdq[0]; + __m128i b = pdq[1]; + const __m128i C = pdq[2]; + __m128i d = pdq[3]; + __m128i t; + __m128i c; + + a = _mm_add_epi32(a, d); + b = _mm_sub_epi32(b, C); + t = _mm_sub_epi32(a, b); + t = _mm_srai_epi32(t, 1); + c = _mm_sub_epi32(t, d); + d = _mm_sub_epi32(t, C); + a = _mm_sub_epi32(a, d); + b = _mm_add_epi32(b, c); + + pdq[0] = a; + pdq[1] = b; + pdq[2] = c; + pdq[3] = d; +} + +Void strIDCT4x4Stage1_OPT_H1(PixelI* p) +{ + /** top left corner, butterfly => butterfly **/ + strDCT2x2up_OPT(p + 0, p + 1, p + 2, p + 3); + + /** top right corner, -pi/8 rotation => butterfly **/ + invOdd_OPT(p + 5, p + 4, p + 7, p + 6); + + /** bottom left corner, butterfly => -pi/8 rotation **/ + invOdd_OPT(p + 10, p + 8, p + 11, p + 9); + + /** bottom right corner, -pi/8 rotation => -pi/8 rotation **/ + invOddOdd_OPT(p + 15, p + 14, p + 13, p + 12); +} + +FORCE_INLINE Void strIDCT4x4Stage1_OPT_H2(PixelI* p) +{ + /** butterfly **/ + strDCT2x2dn_SSE2_1(p); +} + +Void strIDCT4x4Stage1_OPT5(PixelI* p0, PixelI* p1) +{ + _mm_prefetch((char*)(p0 - 96 + 256), _MM_HINT_T0); + strIDCT4x4Stage1_OPT_H1(p0 - 96); + strIDCT4x4Stage1_OPT_H1(p0 - 80); + strIDCT4x4Stage1_OPT_H1(p0 - 32); + strIDCT4x4Stage1_OPT_H1(p0 - 16); + + _mm_prefetch((char*)(p0 - 32 + 256), _MM_HINT_T0); + strIDCT4x4Stage1_OPT_H1(p0 + 32); + strIDCT4x4Stage1_OPT_H1(p0 + 48); + strIDCT4x4Stage1_OPT_H1(p0 + 96); + strIDCT4x4Stage1_OPT_H1(p0 + 112); + + _mm_prefetch((char*)(p0 + 32 + 256), _MM_HINT_T0); + strIDCT4x4Stage1_OPT_H1(p1 - 128); + strIDCT4x4Stage1_OPT_H1(p1 - 112); + strIDCT4x4Stage1_OPT_H1(p1 - 64); + strIDCT4x4Stage1_OPT_H1(p1 - 48); + + _mm_prefetch((char*)(p0 + 96 + 256), _MM_HINT_T0); + strIDCT4x4Stage1_OPT_H1(p1 + 0); + strIDCT4x4Stage1_OPT_H1(p1 + 16); + strIDCT4x4Stage1_OPT_H1(p1 + 64); + strIDCT4x4Stage1_OPT_H1(p1 + 80); + + strIDCT4x4Stage1_OPT_H2(p0 - 96); + strIDCT4x4Stage1_OPT_H2(p0 - 80); + strIDCT4x4Stage1_OPT_H2(p0 - 32); + strIDCT4x4Stage1_OPT_H2(p0 - 16); + strIDCT4x4Stage1_OPT_H2(p0 + 32); + strIDCT4x4Stage1_OPT_H2(p0 + 48); + strIDCT4x4Stage1_OPT_H2(p0 + 96); + strIDCT4x4Stage1_OPT_H2(p0 + 112); + + strIDCT4x4Stage1_OPT_H2(p1 - 128); + strIDCT4x4Stage1_OPT_H2(p1 - 112); + strIDCT4x4Stage1_OPT_H2(p1 - 64); + strIDCT4x4Stage1_OPT_H2(p1 - 48); + strIDCT4x4Stage1_OPT_H2(p1 + 0); + strIDCT4x4Stage1_OPT_H2(p1 + 16); + strIDCT4x4Stage1_OPT_H2(p1 + 64); + strIDCT4x4Stage1_OPT_H2(p1 + 80); +} + +//================================ +__declspec(naked) void __stdcall strPost4x4Stage1_alternate_ASM5(PixelI* p0, PixelI* p1) +{ + UNREFERENCED_PARAMETER( p0 ); + UNREFERENCED_PARAMETER( p1 ); + __asm { + push ebp + push ebx + push esi + push edi + + //================ + // pointer array + mov eax, [esp + 20] // $esi = p0 + mov edx, [esp + 24] // $edi = p1 + mov ecx, 4 * 16 + mov ebx, 4 * 48 + + prefetcht0 [eax + 512] + prefetcht0 [eax + 768] + prefetcht0 [eax + 1024] + prefetcht0 [eax + 1280] + + add edx, ecx + add eax, ebx + + push edx + sub edx, ecx + push edx + push edx + sub edx, ebx + push eax + push eax + sub eax, ecx + push eax + push eax + sub eax, ecx + push eax + sub eax, ecx + + push edx + sub edx, ecx + push edx + sub eax, ecx + push edx + sub edx, ebx + push eax + push eax + sub eax, ecx + push eax + push eax + sub eax, ecx + push eax + sub eax, ecx + + push edx + sub edx, ecx + push edx + sub eax, ecx + push edx + sub edx, ebx + push eax + push eax + sub eax, ecx + push eax + push eax + sub eax, ecx + push eax + sub eax, ecx + + push edx + sub edx, ecx + push edx + sub eax, ecx + push edx + push eax + push eax + sub eax, ecx + push eax + push eax + sub eax, ecx + push eax + + mov ebp, (4 + 4) * -16 + push ebp + } +Loop0: + __asm { + mov esi, [esp + (4 + 4) * 16 + 4 + ebp ] // $esi = p0 + mov edi, [esp + (4 + 4) * 16 + 4 + ebp + 4] // $edi = p1 + + //================ + movdqa xmm2, [esi + 4 * 12] // a = xmm2 + movdqa xmm1, [esi + 4 * 72] // b = xmm1 + movdqa xmm6, [edi + 4 * 4] // c = xmm6 + movdqa xmm7, [edi + 4 * 64] // d = xmm7 + + //================ + // buttefly + paddd xmm2, xmm7 + psubd xmm1, xmm6 + + movdqa xmm0, xmm2 // a = xmm0 + psubd xmm2, xmm1 + psrad xmm2, 1 + movdqa xmm3, xmm2 + + psubd xmm2, xmm7 // c = xmm2 + psubd xmm3, xmm6 // d = xmm3 + paddd xmm1, xmm2 + psubd xmm0, xmm3 + + //================ + // bottom right corner: -pi/8 rotation => -pi/8 rotation + pshufd xmm7, xmm3, 0x3 + movd eax, xmm3 + movd edx, xmm7 + pshufd xmm7, xmm3, 0x1 + movd ebx, xmm7 + pshufd xmm7, xmm3, 0x2 + movd ecx, xmm7 + + add edx, eax + sub ecx, ebx + mov esi, edx + sar esi, 1 + mov edi, ecx + sar edi, 1 + sub eax, esi + add ebx, edi + + lea ebp, [ebx + ebx * 2 + 6] + sar ebp, 3 + sub eax, ebp + lea ebp, [eax + eax * 2 + 2] + sar ebp, 2 + add ebx, ebp + lea ebp, [ebx + ebx * 2 + 4] + sar ebp, 3 + sub eax, ebp + + mov ebp, [esp] + + sub ebx, edi + add eax, esi + add ecx, ebx + sub edx, eax + + mov esi, [esp + (4 + 4) * 16 + 4 + ebp ] // $esi = p0 + mov edi, [esp + (4 + 4) * 16 + 4 + ebp + 4] // $edi = p1 + + movd xmm3, eax + movd xmm4, ebx + movd xmm5, ecx + movd xmm6, edx + punpckldq xmm3, xmm4 + punpckldq xmm5, xmm6 + punpcklqdq xmm3, xmm5 + + //================ + // anti diagonal corners: rotation by -pi/8 + movdqa xmm5, g_const_d1 + movdqa xmm6, g_const_d1 + + pshufd xmm2, xmm2, 0xd8 // 7, 5, 6, 4 + movdqa xmm4, xmm1 // 75, 74, 73, 72 + punpckhqdq xmm1, xmm2 // 7, 5, 75, 74 + punpcklqdq xmm4, xmm2 // 6, 4, 73, 72 + + paddd xmm5, xmm1 + psrad xmm5, 1 + psubd xmm4, xmm5 + + paddd xmm6, xmm4 + psrad xmm6, 1 + paddd xmm1, xmm6 + + movdqa xmm2, xmm4 // 6, 4, 73, 72 + punpckhqdq xmm4, xmm1 // 7, 5, 6, 4 + punpcklqdq xmm2, xmm1 // 75, 74, 73, 72 + pshufd xmm4, xmm4, 0xd8 // 7, 6, 5, 4 + + //================ + // butterfly + // a = xmm0, b = xmm2, c = xmm4, d = xmm3 + paddd xmm0, xmm3 + movdqa xmm1, xmm0 // a = xmm1 + psrad xmm0, 1 + psubd xmm0, xmm3 // d = xmm0 + + movdqa xmm3, xmm0 // d = xmm3 + paddd xmm0, xmm0 + paddd xmm0, xmm3 + psrad xmm0, 3 + paddd xmm1, xmm0 + + movdqa xmm0, xmm1 // a = xmm0 + paddd xmm1, xmm1 + paddd xmm1, xmm0 + psrad xmm1, 4 + paddd xmm3, xmm1 + + movdqa xmm5, xmm0 // a + psrad xmm5, 7 + paddd xmm3, xmm5 // d += (a >> 7) + psrad xmm5, 3 + psubd xmm3, xmm5 // d -= (a >> 10) + + movdqa xmm5, [g_const_d4] + movdqa xmm1, xmm3 // d = xmm1 + psubd xmm2, xmm4 + paddd xmm5, xmm3 + paddd xmm3, xmm3 + paddd xmm3, xmm5 + psrad xmm3, 3 + paddd xmm0, xmm3 + + movdqa xmm3, xmm2 // b = xmm3 + psrad xmm2, 1 + psubd xmm1, xmm2 + + movdqa xmm2, xmm0 // a = xmm2 + psubd xmm0, xmm3 + psrad xmm0, 1 + psubd xmm0, xmm4 // c = xmm0 + + paddd xmm3, xmm1 + psubd xmm2, xmm0 + + //================ + movdqa [edi + 4 * 4], xmm1 + movdqa [edi + 4 * 64], xmm0 + movdqa [esi + 4 * 12], xmm2 + movdqa [esi + 4 * 72], xmm3 + + add ebp, 8 + mov [esp], ebp + jnz Loop0 + + //================ + add esp, (4 + 4) * 16 + 4 + pop edi + pop esi + pop ebx + pop ebp + ret 4 * 2 + } +} + +Int invTransformMacroblock_YUV444_Center5(CWMImageStrCodec * pSC) +{ + const OVERLAP olOverlap = pSC->WMISCP.olOverlap; + int i = 0; + + assert(0 < pSC->cRow && pSC->cRow < pSC->cmbHeight); + assert(0 < pSC->cColumn && pSC->cColumn < pSC->cmbWidth); + + assert(0 == pSC->WMII.cPostProcStrength); + + assert(YUV_444 == pSC->m_param.cfColorFormat); + assert(3 == pSC->m_param.cNumChannels); + + assert(pSC->m_Dparam->bDecodeFullWidth); + assert(1 == pSC->m_Dparam->cThumbnailScale); + + for (i = 0; i < 3; ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[i]; + PixelI* const p1 = pSC->p1MBbuffer[i]; + + //================================ + // second level inverse transform + strIDCT4x4Stage2(p1); + if (pSC->m_param.bScaledArith) { + strNormalizeDec(p1, (i != 0)); + } + + //================================ + // second level inverse overlap + if (OL_TWO <= olOverlap) + { + strPost4x4Stage2Split_alternate(p0, p1); + } + + //================================ + // first level inverse transform + strIDCT4x4Stage1_OPT5(p0, p1); + + //================================ + // first level inverse overlap + if (OL_ONE <= olOverlap) + { + strPost4x4Stage1_alternate_ASM5(p0, p1); + } + } + + return ICERR_OK; +} +#endif +#endif + +//================================================================ +void StrDecOpt(CWMImageStrCodec* pSC) +{ +#if defined(WMP_OPT_SSE2) + if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) + { + CWMImageInfo* pII = &pSC->WMII; + // CWMIStrCodecParam* pSCP = &pSC->WMISCP; + + g_const_d0 = _mm_setzero_si128(); + g_const_d3 = _mm_set1_epi32(3); + g_const_d1 = _mm_set_epi32(1, 1, 1, 1); + g_const_d4 = _mm_set_epi32(4, 4, 4, 4); + + g_const_d0x80 = _mm_set_epi32(0x80, 0x80, 0x80, 0x80); + g_const_w0x80 = _mm_set_epi16(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80); + g_const_b0x80 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80); + + if (pSC->WMII.fPaddedUserBuffer && + //pSC->m_Dparam->bDecodeFullFrame && + //((pII->cWidth & 0xf) == 0) && + //(((int) pSC->WMIBI.pv & 0xf) == 0) && + BD_8 == pII->bdBitDepth && + CF_RGB == pII->cfColorFormat && + 24 == pII->cBitsPerUnit && + pII->bRGB && + O_NONE == pII->oOrientation && + YUV_444 == pSC->m_param.cfColorFormat && + pSC->p1MBbuffer[1] - pSC->p1MBbuffer[0] == pSC->p1MBbuffer[2] - pSC->p1MBbuffer[1] && + pSC->m_Dparam->bDecodeFullFrame && + 1) + { +#if defined(WMP_OPT_CC_DEC) + if (pSC->m_param.bScaledArith || pSC->WMISCP.olOverlap != OL_NONE) + { + pSC->Load = outputMBRow_RGB24_Lossy_3; + } + else + { + pSC->Load = outputMBRow_RGB24_Lossless_1; + } +#endif // WMP_OPT_CC_DEC + } + + if (YUV_444 == pSC->m_param.cfColorFormat && + pSC->p1MBbuffer[1] - pSC->p1MBbuffer[0] == pSC->p1MBbuffer[2] - pSC->p1MBbuffer[1] && + pSC->m_Dparam->bDecodeFullWidth && + pSC->m_param.cSubVersion == CODEC_SUBVERSION_NEWSCALING_SOFT_TILES && + 1 == pSC->m_Dparam->cThumbnailScale) + { +#if defined(WMP_OPT_TRFM_DEC) + pSC->TransformCenter = invTransformMacroblock_YUV444_Center5; +#endif + } + + } +#else + UNREFERENCED_PARAMETER( pSC ); +#endif +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/encode.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/encode.c new file mode 100644 index 0000000..10a9672 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/encode.c @@ -0,0 +1,144 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include +#include +#include "encode.h" +#include "strcodec.h" +#include "common.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +/************************************************************************* + Context allocation + In theory it is possible to independently set uiTrimFlexBits for + each tile, but for now we assume only one user specified value is + used for the entire image +*************************************************************************/ +Int AllocateCodingContextEnc(CWMImageStrCodec *pSC, Int iNumContexts, Int iTrimFlexBits) +{ + Int i, iCBPSize, k; + static const Int aAlphabet[] = {5,4,8,7,7, 12,6,6,12,6,6,7,7, 12,6,6,12,6,6,7,7}; + + if (iTrimFlexBits < 0) + iTrimFlexBits = 0; + else if (iTrimFlexBits > 15) + iTrimFlexBits = 15; + pSC->m_param.bTrimFlexbitsFlag = (iTrimFlexBits > 0); + + if (iNumContexts < 1 || iNumContexts > MAX_TILES) // only between 1 and 256 allowed + return ICERR_ERROR; + + if (pSC == NULL) + return ICERR_ERROR; + + pSC->m_pCodingContext = malloc (iNumContexts * sizeof (CCodingContext)); + if (pSC->m_pCodingContext == NULL) { + pSC->cNumCodingContext = 0; + return ICERR_ERROR; + } + memset (pSC->m_pCodingContext, 0, iNumContexts * sizeof (CCodingContext)); + + pSC->cNumCodingContext = iNumContexts; + iCBPSize = (pSC->m_param.cfColorFormat == Y_ONLY || pSC->m_param.cfColorFormat == NCOMPONENT + || pSC->m_param.cfColorFormat == CMYK) ? 5 : 9; + + /** allocate / initialize members **/ + for (i = 0; i < iNumContexts; i++) { + CCodingContext *pContext = &(pSC->m_pCodingContext[i]); + + /** allocate adaptive Huffman encoder **/ + pContext->m_pAdaptHuffCBPCY = Allocate (iCBPSize, ENCODER); + if(pContext->m_pAdaptHuffCBPCY == NULL) { + return ICERR_ERROR; + } + pContext->m_pAdaptHuffCBPCY1 = Allocate(5, ENCODER); + if(pContext->m_pAdaptHuffCBPCY1 == NULL){ + return ICERR_ERROR; + } + + for(k = 0; k < NUMVLCTABLES; k ++){ + pContext->m_pAHexpt[k] = Allocate(aAlphabet[k], ENCODER); + if(pContext->m_pAHexpt[k] == NULL){ + return ICERR_ERROR; + } + } + + ResetCodingContextEnc(pContext); + pContext->m_iTrimFlexBits = iTrimFlexBits; + } + + return ICERR_OK; +} + +/************************************************************************* + Context reset on encoder +*************************************************************************/ +Void ResetCodingContextEnc(CCodingContext *pContext) +{ + Int k; + /** set flags **/ + pContext->m_pAdaptHuffCBPCY->m_bInitialize = FALSE; + pContext->m_pAdaptHuffCBPCY1->m_bInitialize = FALSE; + for(k = 0; k < NUMVLCTABLES; k ++) + pContext->m_pAHexpt[k]->m_bInitialize = FALSE; + + // reset VLC tables + AdaptLowpassEnc (pContext); + AdaptHighpassEnc (pContext); + + // reset zigzag patterns, totals + InitZigzagScan(pContext); + // reset bit reduction and cbp models + ResetCodingContext(pContext); +} + +/************************************************************************* + Context deletion +*************************************************************************/ +Void FreeCodingContextEnc(CWMImageStrCodec *pSC) +{ + Int iContexts = (Int)(pSC->cNumCodingContext), i, k; + if (iContexts > 0 && pSC->m_pCodingContext) { + + for (i = 0; i < iContexts; i++) { + CCodingContext *pContext = &(pSC->m_pCodingContext[i]); + Clean (pContext->m_pAdaptHuffCBPCY); + Clean (pContext->m_pAdaptHuffCBPCY1); + for (k = 0; k < NUMVLCTABLES; k++) + Clean (pContext->m_pAHexpt[k]); + } + free (pSC->m_pCodingContext); + } +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/encode.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/encode.h new file mode 100644 index 0000000..2028d04 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/encode.h @@ -0,0 +1,113 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#ifndef WMI_ENCODE_H +#define WMI_ENCODE_H + +#include "strcodec.h" + +/************************************************************************* + struct / class definitions +*************************************************************************/ + +Int EncodeMacroblockDC(CWMImageStrCodec*, CCodingContext *, Int, Int); +Int EncodeMacroblockLowpass(CWMImageStrCodec*, CCodingContext *, Int, Int); +Int EncodeMacroblockHighpass(CWMImageStrCodec*, CCodingContext *, Int, Int); + +Int quantizeMacroblock(CWMImageStrCodec *); +Void transformMacroblock(CWMImageStrCodec *); +Void predMacroblockEnc(CWMImageStrCodec *); + +Void AdaptLowpassEnc(CCodingContext *pContext); +Void AdaptHighpassEnc(CCodingContext *pContext); +Void ResetCodingContextEnc(CCodingContext *pContext); +Int AllocateCodingContextEnc(struct CWMImageStrCodec *pSC, Int iNumContexts, Int iTrimFlexBits); +Void FreeCodingContextEnc(struct CWMImageStrCodec *pSC); +Void predCBPEnc(CWMImageStrCodec *pSC, CCodingContext *pContext); + +/************************************************************************* + Forward transform definitions +*************************************************************************/ +/** 2-point pre filter for boundaries (only used in 420 UV DC subband) **/ +Void strPre2(PixelI *, PixelI *); + +/** 2x2 pre filter (only used in 420 UV DC subband) **/ +Void strPre2x2(PixelI *, PixelI *, PixelI *, PixelI *); + +/** 4-point pre filter for boundaries **/ +Void strPre4(PixelI *, PixelI *, PixelI *, PixelI *); + +/** data allocation in working buffer (first stage) **/ + +/** Y, 444 U and V **/ +/** 0 1 2 3 **/ +/** 32 33 34 35 **/ +/** 64 65 66 67 **/ +/** 96 97 98 99 **/ + +/** 420 U and V **/ +/** 0 2 4 6 **/ +/** 64 66 68 70 **/ +/** 128 130 132 134 **/ +/** 192 194 196 198 **/ + +/** 4x4 foward DCT for first stage **/ +Void strDCT4x4FirstStage(PixelI *); +Void strDCT4x4FirstStage420UV(PixelI *); + +Void strDCT4x4Stage1(PixelI*); + +/** 4x4 pre filter for first stage **/ +Void strPre4x4FirstStage(PixelI *); +Void strPre4x4FirstStage420UV(PixelI *); + +Void strPre4x4Stage1Split(PixelI* p0, PixelI* p1, Int iOffset); +Void strPre4x4Stage1(PixelI* p, Int iOffset); + +/** data allocation in working buffer (second stage)**/ + +/** Y, 444 U and V **/ +/** 0 4 8 12 **/ +/** 128 132 136 140 **/ +/** 256 260 264 268 **/ +/** 384 388 392 396 **/ + +/** 420 U and V **/ +/** 0 8 **/ +/** 256 264 **/ + +/** 4x4 foward DCT for second stage **/ +Void strDCT4x4SecondStage(PixelI *); +Void strNormalizeEnc(PixelI *, Bool); +Void strDCT2x2dnEnc(PixelI *, PixelI *, PixelI *, PixelI *); + +/** 4x4 pre filter for second stage **/ +Void strPre4x4Stage2Split(PixelI* p0, PixelI* p1); + +#endif // ENCODE_H + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/segenc.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/segenc.c new file mode 100644 index 0000000..d4a8cd3 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/segenc.c @@ -0,0 +1,1186 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include +#include +#include "strcodec.h" +#include "encode.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +/** local function definitions **/ +#ifdef X86OPT_INLINE +__forceinline +#endif +static Int EncodeBlock (Bool bChroma, const Int *aLocalCoef, Int iNumNonzero, + struct CAdaptiveHuffman **pAHexpt, + Int iContextOffset, BitIOInfo* pOut, UInt iLocation); + +/************************************************************************* + EncodeSignificantAbsLevel +*************************************************************************/ +#ifdef X86OPT_INLINE +//__forceinline +#endif +static Void EncodeSignificantAbsLevel (UInt iAbsLevel, struct CAdaptiveHuffman *pAHexpt, BitIOInfo* pOut) +{ + Int iIndex, iFixed, aIndex[] = { 0,1,2,2, 3,3,3,3, 4,4,4,4, 5,5,5,5 }; + Int aFixedLength[] = { 0, 0, 1, 2, 2, 2 }; + + assert(iAbsLevel > 0); + iAbsLevel--; + if (iAbsLevel >= 16) { + Int i = iAbsLevel; + iIndex = 6; + /** find leftmost bit **/ + i >>= 5; + iFixed = 4; + while (i) { /** caution - infinite loop if not careful **/ + iFixed++; + assert (iFixed < 30); + i >>= 1; + } + + pAHexpt->m_iDiscriminant += pAHexpt->m_pDelta[iIndex]; + putBit16z(pOut, pAHexpt->m_pTable[iIndex * 2 + 1], pAHexpt->m_pTable[iIndex * 2 + 2]); + if (iFixed > 18) { + putBit16z (pOut, 15, 4); + if (iFixed > 21) { + putBit16z (pOut, 3, 2); + putBit16 (pOut, iFixed - 22, 3); // 22 - 29 + } + else + putBit16z (pOut, iFixed - 19, 2); // 19 20 21 + } + else { + putBit16z(pOut, (iFixed - 4), 4); + } + putBit32(pOut, iAbsLevel, iFixed); + } + else { + iIndex = aIndex[iAbsLevel]; + iFixed = aFixedLength[iIndex]; + + pAHexpt->m_iDiscriminant += pAHexpt->m_pDelta[iIndex]; + putBit16z(pOut, pAHexpt->m_pTable[iIndex * 2 + 1], pAHexpt->m_pTable[iIndex * 2 + 2]); + putBit32(pOut, iAbsLevel, iFixed); + } +} + +/************************************************************************* + EncodeMacroblockDC +*************************************************************************/ + +Void encodeQPIndex(BitIOInfo* pIO, U8 iIndex,U8 cBits) +{ + if(iIndex == 0) + putBit16z(pIO, 0, 1); + else{ + putBit16z(pIO, 1, 1); + putBit16z(pIO, iIndex - 1, cBits); + } +} + +Int EncodeMacroblockDC (CWMImageStrCodec *pSC, CCodingContext *pContext, Int iMBX, Int iMBY) +{ + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + BitIOInfo* pIO = pContext->m_pIODC; + CWMIMBInfo *pMBInfo = &pSC->MBInfo; + Int iIndex, j = 0; + struct CAdaptiveHuffman *pAH; + Int aLaplacianMean[2] = { 0, 0}, *pLM = aLaplacianMean; + Int iModelBits = pContext->m_aModelDC.m_iFlcBits[0]; + COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (Int) pSC->m_param.cNumChannels; + + UNREFERENCED_PARAMETER( iMBX ); + UNREFERENCED_PARAMETER( iMBY ); + + writeIS_L1(pSC, pIO); + + if(pSC->m_param.bTranscode == FALSE){ + pMBInfo->iQIndexLP = (U8)(pTile->cNumQPLP > 1 ? (rand() % pTile->cNumQPLP) : 0); + pMBInfo->iQIndexHP = (U8)(pTile->cNumQPHP > 1 ? (rand() % pTile->cNumQPHP) : 0); + } + if(pTile->cBitsHP == 0 && pTile->cNumQPHP > 1) // use LP QP + pMBInfo->iQIndexHP = pMBInfo->iQIndexLP; + + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL && pSC->WMISCP.sbSubband != SB_DC_ONLY){ + if(pTile->cBitsLP > 0) // MB-based LP QP index + encodeQPIndex(pIO, pMBInfo->iQIndexLP, pTile->cBitsLP); + if( pSC->WMISCP.sbSubband != SB_NO_HIGHPASS && pTile->cBitsHP > 0) // MB-based HP QP index + encodeQPIndex(pIO, pMBInfo->iQIndexHP, pTile->cBitsHP); + } + + if(pSC->m_param.bTranscode == FALSE) + pSC->Quantize(pSC); + + predMacroblockEnc(pSC); + + /** code path for Y_ONLY, CMYK and N_CHANNEL DC **/ + if(cf == Y_ONLY || cf == CMYK || cf == NCOMPONENT) { + Int iQDC, iDC, iSign; + for (j = 0; j < iChannels; j++) { + iDC = pMBInfo->iBlockDC[j][0]; + iSign = (iDC < 0); + iDC = abs(iDC); + iQDC = iDC >> iModelBits; + + /** send luminance DC **/ + if (iQDC) { + putBit16z(pIO, 1, 1); + EncodeSignificantAbsLevel((UInt) iQDC, pContext->m_pAHexpt[3], pIO); + *pLM += 1; + } + else { + putBit16z(pIO, 0, 1); + } + + putBit16(pIO, iDC, iModelBits); + if (iDC) { + putBit16z(pIO, iSign, 1); + } + + pLM = aLaplacianMean + 1; + iModelBits = pContext->m_aModelDC.m_iFlcBits[1]; + } + } + else { /** code path for YUV DC **/ + Int iDCY, iDCU, iDCV, iQDCY, iQDCU, iQDCV; + + pAH = pContext->m_pAHexpt[2]; + iQDCY = abs(iDCY = pMBInfo->iBlockDC[0][0]); + iQDCU = abs(iDCU = pMBInfo->iBlockDC[1][0]); + iQDCV = abs(iDCV = pMBInfo->iBlockDC[2][0]); + if (iModelBits) { + iQDCY >>= iModelBits; + } + + iModelBits = pContext->m_aModelDC.m_iFlcBits[1]; + if (iModelBits) { + iQDCU >>= iModelBits; + iQDCV >>= iModelBits; + } + iModelBits = pContext->m_aModelDC.m_iFlcBits[0]; + + iIndex = (iQDCY != 0) * 4 + (iQDCU != 0) * 2 + (iQDCV != 0); + putBit16z(pIO, pAH->m_pTable[iIndex * 2 + 1], pAH->m_pTable[iIndex * 2 + 2]); + + /** send luminance DC **/ + if (iQDCY) { + EncodeSignificantAbsLevel((UInt) iQDCY, pContext->m_pAHexpt[3], pIO); + *pLM += 1; + } + putBit16(pIO, abs(iDCY), iModelBits); + if (iDCY) { + putBit16z(pIO, (iDCY < 0), 1); + } + + /** send chroma DC **/ + pLM = aLaplacianMean + 1; + iModelBits = pContext->m_aModelDC.m_iFlcBits[1]; + + if (iQDCU) { + EncodeSignificantAbsLevel((UInt) iQDCU, pContext->m_pAHexpt[4], pIO); + *pLM += 1; + } + putBit16(pIO, abs(iDCU), iModelBits); + if (iDCU) { + putBit16z(pIO, (iDCU < 0), 1); + } + + if (iQDCV) { + EncodeSignificantAbsLevel((UInt) iQDCV, pContext->m_pAHexpt[4], pIO); + *pLM += 1; + } + putBit16(pIO, abs(iDCV), iModelBits); + if (iDCV) { + putBit16z(pIO, (iDCV < 0), 1); + } + } + + UpdateModelMB (cf, iChannels, aLaplacianMean, &(pContext->m_aModelDC)); + + if (pSC->m_bResetContext && pSC->WMISCP.sbSubband == SB_DC_ONLY) { + AdaptDiscriminant(pContext->m_pAHexpt[2]); + AdaptDiscriminant(pContext->m_pAHexpt[3]); + AdaptDiscriminant(pContext->m_pAHexpt[4]); + } + + return ICERR_OK; +} + +/************************************************************************* + Scan block with zero model bits +*************************************************************************/ +#ifdef X86OPT_INLINE +__forceinline +#endif +static Int AdaptiveScanZero (const PixelI *pCoeffs, CAdaptiveScan *pScan, + Int *pRLCoeffs, const Int iCount) +{ + Int k, iRun = 1, iLevel, iNumNonzero = 0; + + iLevel = pCoeffs[pScan[1].uScan]; + if (iLevel) { + pScan[1].uTotal++; + pRLCoeffs[iNumNonzero * 2] = 0; + pRLCoeffs[iNumNonzero * 2 + 1] = iLevel; + iNumNonzero++; + iRun = 0; + } + for (k = 2; k < iCount; k++) { + iLevel = pCoeffs[pScan[k].uScan]; + iRun++; + if (iLevel) { + pScan[k].uTotal++; + if (pScan[k].uTotal > pScan[k - 1].uTotal) { + CAdaptiveScan cTemp = pScan[k]; + pScan[k] = pScan[k - 1]; + pScan[k - 1] = cTemp; + } + pRLCoeffs[iNumNonzero * 2] = iRun - 1; + pRLCoeffs[iNumNonzero * 2 + 1] = iLevel; + iNumNonzero++; + iRun = 0; + } + } + return iNumNonzero; +} + +/************************************************************************* + Scan block with nonzero model bits, all trimmed +*************************************************************************/ +#ifdef X86OPT_INLINE +__forceinline +#endif +static Int AdaptiveScanTrim (const PixelI *pCoeffs, CAdaptiveScan *pScan, + const Int iModelBits, Int *pRLCoeffs, const Int iCount) +{ + Int k, iRun = 1, iLevel, iNumNonzero = 0; + Int iTemp; + unsigned int iThOff = (1 << iModelBits) - 1, iTh = iThOff * 2 + 1; + + iLevel = pCoeffs[pScan[1].uScan]; + + if ((unsigned int)(iLevel + iThOff) >= iTh) { + iTemp = abs (iLevel) >> iModelBits; + pScan[1].uTotal++; + pRLCoeffs[iNumNonzero * 2] = 0; + pRLCoeffs[iNumNonzero * 2 + 1] = (iLevel < 0) ? -iTemp : iTemp; + iNumNonzero++; + iRun = 0; + } + for (k = 2; k < iCount; k++) { + iRun++; + iLevel = pCoeffs[pScan[k].uScan]; + if ((unsigned int)(iLevel + iThOff) >= iTh) { + iTemp = abs (iLevel) >> iModelBits; + pScan[k].uTotal++; + if (pScan[k].uTotal > pScan[k - 1].uTotal) { + CAdaptiveScan cTemp = pScan[k]; + pScan[k] = pScan[k - 1]; + pScan[k - 1] = cTemp; + } + pRLCoeffs[iNumNonzero * 2] = iRun - 1; + pRLCoeffs[iNumNonzero * 2 + 1] = (iLevel < 0) ? -iTemp : iTemp; + iNumNonzero++; + iRun = 0; + } + } + return iNumNonzero; +} + +/************************************************************************* + Scan block with nonzero model bits +*************************************************************************/ +/** saves around 1.5% at QP=1 (no SIMD opt) **/ +#define USE_GRES_LUT +#ifdef USE_GRES_LUT +static const Int gRes[] = { +65*2+1, 63*2+1, 61*2+1, 59*2+1, 57*2+1, 55*2+1, 53*2+1, 51*2+1, 49*2+1, 47*2+1, 45*2+1, 43*2+1, 41*2+1, +39*2+1, 37*2+1, 35*2+1, 33*2+1, 31*2+1, 29*2+1, 27*2+1, 25*2+1, 23*2+1, 21*2+1, 19*2+1, 17*2+1, 15*2+1, +13*2+1, 11*2+1, 9*2+1, 7*2+1, 5*2+1, 3*2+1, +0, +2*2+1, 4*2+1, 6*2+1, 8*2+1, 10*2+1, 12*2+1, 14*2+1, 16*2+1, 18*2+1, 20*2+1, 22*2+1, 24*2+1, +26*2+1, 28*2+1, 30*2+1, 32*2+1, 34*2+1, 36*2+1, 38*2+1, 40*2+1, 42*2+1, 44*2+1, 46*2+1, 48*2+1, 50*2+1, +52*2+1, 54*2+1, 56*2+1, 58*2+1, 60*2+1, 62*2+1, 64*2+1 }; +#endif // USE_GRES_LUT + +#ifdef X86OPT_INLINE +//__forceinline +#endif +static Int AdaptiveScan (const PixelI *pCoeffs, Int *pResidual, + CAdaptiveScan *pScan, + const Int iModelBits, const Int iTrimBits, + Int *pRLCoeffs, const Int iCount) +{ + if (iModelBits == 0) { + return AdaptiveScanZero (pCoeffs, pScan, pRLCoeffs, iCount); + } + else if (iModelBits <= iTrimBits) { + return AdaptiveScanTrim (pCoeffs, pScan, iModelBits, pRLCoeffs, iCount); + } + else if (iTrimBits == 0 +#ifdef USE_GRES_LUT + && iModelBits < 6 +#endif // USE_GRES_LUT + ) { + Int k, iRun = 0, iLevel, iNumNonzero = 0; + Int iTemp, iTemp1; + const unsigned int iThOff = (1 << iModelBits) - 1, iTh = iThOff * 2 + 1; + + iLevel = pCoeffs[pScan[1].uScan]; + + if ((unsigned int)(iLevel + iThOff) >= iTh) { + iTemp1 = abs (iLevel); + iTemp = iTemp1 >> iModelBits; + pResidual[pScan[1].uScan] = (iTemp1 & iThOff) * 2; + pScan[1].uTotal++; + pRLCoeffs[iNumNonzero * 2] = iRun; + pRLCoeffs[iNumNonzero * 2 + 1] = (iLevel < 0) ? -iTemp : iTemp; + iNumNonzero++; + iRun = 0; + } + else { + iRun++; +#ifdef USE_GRES_LUT + pResidual[pScan[1].uScan] = gRes[(iLevel + 32)]; +#else // USE_GRES_LUT + iTemp = -(iLevel < 0); + pResidual[pScan[1].uScan] = (iLevel ^ iTemp) * 4 + (6 & iTemp) + (iLevel != 0); +#endif // USE_GRES_LUT + } + for (k = 2; k < iCount; k++) { + const Int sk = pScan[k].uScan; + //pResidual++; + iLevel = pCoeffs[sk]; + if ((unsigned int)(iLevel + iThOff) >= iTh) { + const Int iSign = -(iLevel < 0); + iTemp1 = (iSign ^ iLevel) - iSign; + iTemp = iTemp1 >> iModelBits; + pResidual[sk] = (iTemp1 & iThOff) * 2; + pScan[k].uTotal++; + if (pScan[k].uTotal > pScan[k - 1].uTotal) { + CAdaptiveScan cTemp = pScan[k]; + pScan[k] = pScan[k - 1]; + pScan[k - 1] = cTemp; + } + pRLCoeffs[iNumNonzero * 2] = iRun; + pRLCoeffs[iNumNonzero * 2 + 1] = (iTemp ^ iSign) - iSign; + iNumNonzero++; + iRun = 0; + } + else { + iRun++; +#ifdef USE_GRES_LUT + pResidual[sk] = gRes[(iLevel + 32)]; +#else // USE_GRES_LUT + iTemp = -(iLevel < 0); + pResidual[sk] = (iLevel ^ iTemp) * 4 + (6 & iTemp) + (iLevel != 0); +#endif // USE_GRES_LUT + ////(abs(iLevel) * 4) + ((iLevel < 0) * 2) + (iLevel != 0); + } + } + return iNumNonzero; + } + else { + Int k, iRun = 0, iLevel, iNumNonzero = 0; + Int iTemp, iTemp1; + const unsigned int iThOff = (1 << iModelBits) - 1, iTh = iThOff * 2 + 1; + + iLevel = pCoeffs[pScan[1].uScan]; + //pResidual++; + if ((unsigned int)(iLevel + iThOff) >= iTh) { + iTemp1 = abs (iLevel); + iTemp = iTemp1 >> iModelBits; + pResidual[pScan[1].uScan] = ((iTemp1 & iThOff) >> iTrimBits) * 2; + pScan[1].uTotal++; + pRLCoeffs[iNumNonzero * 2] = iRun; + pRLCoeffs[iNumNonzero * 2 + 1] = (iLevel < 0) ? -iTemp : iTemp; + iNumNonzero++; + iRun = 0; + } + else { + iRun++; + iTemp = -(iLevel < 0); + iLevel = ((iLevel + iTemp) >> iTrimBits) - iTemp; // round towards zero + iTemp = -(iLevel < 0); + pResidual[pScan[1].uScan] = (iLevel ^ iTemp) * 4 + (6 & iTemp) + (iLevel != 0); + } + for (k = 2; k < iCount; k++) { + const Int sk = pScan[k].uScan; + //pResidual++; + iLevel = pCoeffs[sk]; + if ((unsigned int)(iLevel + iThOff) >= iTh) { + iTemp1 = abs (iLevel); + iTemp = iTemp1 >> iModelBits; + pResidual[sk] = ((iTemp1 & iThOff) >> iTrimBits) * 2; + pScan[k].uTotal++; + if (pScan[k].uTotal > pScan[k - 1].uTotal) { + CAdaptiveScan cTemp = pScan[k]; + pScan[k] = pScan[k - 1]; + pScan[k - 1] = cTemp; + } + pRLCoeffs[iNumNonzero * 2] = iRun; + pRLCoeffs[iNumNonzero * 2 + 1] = (iLevel < 0) ? -iTemp : iTemp; + iNumNonzero++; + iRun = 0; + } + else { + iRun++; + iTemp = -(iLevel < 0); + iLevel = ((iLevel + iTemp) >> iTrimBits) - iTemp; // round towards zero + iTemp = -(iLevel < 0); + pResidual[sk] = (iLevel ^ iTemp) * 4 + (6 & iTemp) + (iLevel != 0); + } + } + return iNumNonzero; + } +} + +/************************************************************************* + EncodeMacroblockLowpass +*************************************************************************/ +Int EncodeMacroblockLowpass (CWMImageStrCodec *pSC, CCodingContext *pContext, Int iMBX, Int iMBY) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (Int) pSC->m_param.cNumChannels; + Int iFullChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : iChannels; + CWMIMBInfo *pMBInfo = &pSC->MBInfo; + BitIOInfo* pIO = pContext->m_pIOLP; + + CAdaptiveScan *pScan = pContext->m_aScanLowpass; + Int k, /*iPrevRun = -1,*/ iRun = 0;// iLastIndex = 0; + Int iModelBits = pContext->m_aModelLP.m_iFlcBits[0]; + PixelI aBuf[2][8]; + Int aLaplacianMean[2] = {0, 0}, *pLM = aLaplacianMean; + Int iChannel, iVal; + Int aRLCoeffs[MAX_CHANNELS][32], iNumCoeffs[MAX_CHANNELS]; + const I32 *aDC[MAX_CHANNELS]; + Int aResidual[MAX_CHANNELS][16]; + Void (*putBits)(BitIOInfo* pIO, U32 uiBits, U32 cBits) = putBit16; + + UNREFERENCED_PARAMETER( iMBX ); + UNREFERENCED_PARAMETER( iMBY ); + + if (iChannels > MAX_CHANNELS) + return ICERR_ERROR; + + if((pSC->WMISCP.bfBitstreamFormat != SPATIAL) && (pSC->pTile[pSC->cTileColumn].cBitsLP > 0)) // MB-based LP QP index + encodeQPIndex(pIO, pMBInfo->iQIndexLP, pSC->pTile[pSC->cTileColumn].cBitsLP); + + // set arrays + for (k = 0; k < iChannels; k++) { + aDC[k] = pMBInfo->iBlockDC[k]; + } + + /** reset adaptive scan totals **/ + if (pSC->m_bResetRGITotals) { + int iScale = 2; + int iWeight = iScale * 16; + pScan[0].uTotal = MAXTOTAL; + for (k = 1; k < 16; k++) { + pScan[k].uTotal = iWeight; + iWeight -= iScale; + } + } + + /** scan 4x4 transform **/ + for (iChannel = 0; iChannel < iFullChannels; iChannel++) { + iNumCoeffs[iChannel] = AdaptiveScan (aDC[iChannel], aResidual[iChannel], + pScan, iModelBits, 0, aRLCoeffs[iChannel], 16); + + iModelBits = pContext->m_aModelLP.m_iFlcBits[1]; + } + + if (cf == YUV_420 || cf == YUV_422) { /** interleave U and V **/ + static const Int aRemap[] = { 4, 1,2,3, 5,6,7 }; + const Int *pRemap = aRemap + (cf == YUV_420); + const Int iCount = (cf == YUV_420) ? 6 : 14; + Int iCoef = 0; + + iRun = 0; + iModelBits = pContext->m_aModelLP.m_iFlcBits[1]; + + for (k = 0; k < iCount; k++) { + Int iIndex = pRemap[k >> 1]; + Int iDC = aDC[(k & 1) + 1][iIndex]; + aBuf[k & 1][iIndex] = iVal = abs (iDC) >> iModelBits; + + if (iVal) { + aRLCoeffs[1][iCoef * 2] = iRun; + aRLCoeffs[1][iCoef * 2 + 1] = (iDC < 0) ? -iVal : iVal; + iCoef++; + iRun = 0; + } + else { + iRun++; + } + } + iNumCoeffs[1] = iCoef; + } + + /** in raw mode, this can take 6% of the bits in the extreme low rate case!!! **/ + if (cf == YUV_420 || cf == YUV_422) + iFullChannels = 2; + + if (cf == YUV_420 || cf == YUV_422 || cf == YUV_444) { + int iCBP, iMax = iFullChannels * 4 - 5; /* actually (1 << iNChannels) - 1 **/ + int iCountM = pContext->m_iCBPCountMax, iCountZ = pContext->m_iCBPCountZero; + iCBP = (iNumCoeffs[0] > 0) + (iNumCoeffs[1] > 0) * 2; + if (iFullChannels == 3) + iCBP += (iNumCoeffs[2] > 0) * 4; + + if (iCountZ <= 0 || iCountM < 0) { + iVal = iCBP; + if (iCountM < iCountZ) { + iVal = iMax - iCBP; + } + if (iVal == 0) + putBit16z(pIO, 0, 1); + else if (iVal == 1) + putBit16z(pIO, (iFullChannels + 1) & 0x6, iFullChannels); // 2 or 4 + else + putBit16z(pIO, iVal + iMax + 1, iFullChannels + 1); // cbp + 4 or cbp + 8 + } + else { + putBit16z(pIO, iCBP, iFullChannels); + } + + iCountM += 1 - 4 * (iCBP == iMax);//(b + c - 2*a); + iCountZ += 1 - 4 * (iCBP == 0);//(a + b - 2*c); + if (iCountM < -8) + iCountM = -8; + else if (iCountM > 7) + iCountM = 7; + pContext->m_iCBPCountMax = iCountM; + + if (iCountZ < -8) + iCountZ = -8; + else if (iCountZ > 7) + iCountZ = 7; + pContext->m_iCBPCountZero = iCountZ; + } + else { /** 1 or N channel **/ + for (iChannel = 0; iChannel < iChannels; iChannel++) { + putBit16z(pIO, (iNumCoeffs[iChannel] > 0), 1); + } + } + + // set appropriate function pointer + if (pContext->m_aModelLP.m_iFlcBits[0] > 14 || pContext->m_aModelLP.m_iFlcBits[1] > 14) { + putBits = putBit32; + } + + iModelBits = pContext->m_aModelLP.m_iFlcBits[0]; + + for (iChannel = 0; iChannel < iFullChannels; iChannel++) { + const Int *pRL = aRLCoeffs[iChannel]; + Int iCoef = iNumCoeffs[iChannel]; + + if (iCoef) { + (*pLM) += iCoef; + if(EncodeBlock (iChannel > 0, pRL, iCoef, pContext->m_pAHexpt, CTDC, + pIO, 1 + 9 * ((cf == YUV_420) && (iChannel == 1)) + ((cf == YUV_422) && (iChannel == 1))) != ICERR_OK) + return ICERR_ERROR; + } + + if (iModelBits) { + if ((cf == YUV_420 || cf == YUV_422) && iChannel) { // 420/422 chroma + for (k = 1; k < ((cf == YUV_420) ? 4 : 8); k++) { + putBits(pIO, abs(aDC[1][k]), iModelBits); + if (aBuf[0][k] == 0 && aDC[1][k]) { + putBit16z(pIO, (aDC[1][k] < 0), 1); + } + putBits(pIO, abs(aDC[2][k]), iModelBits); + if (aBuf[1][k] == 0 && aDC[2][k]) { + putBit16z(pIO, (aDC[2][k] < 0), 1); + } + } + } + else { // normal case + for (k = 1; k < 16; k++) { + putBit16z(pIO, aResidual[iChannel][k] >> 1, iModelBits + (aResidual[iChannel][k] & 1)); + } + } + } + + pLM = aLaplacianMean + 1; + iModelBits = pContext->m_aModelLP.m_iFlcBits[1]; + } + + writeIS_L1(pSC, pIO); + + UpdateModelMB (cf, iChannels, aLaplacianMean, &pContext->m_aModelLP); + + if (pSC->m_bResetContext) { + AdaptLowpassEnc(pContext); + } + + return ICERR_OK; +} + +/************************************************************************* + Adapt +*************************************************************************/ +Void AdaptLowpassEnc(CCodingContext *pSC) +{ + Int kk; + for (kk = 0; kk < CONTEXTX + CTDC; kk++) { /** adapt fixed code (index 0 and 1) as well **/ + AdaptDiscriminant (pSC->m_pAHexpt[kk]); + } +} + +Void AdaptHighpassEnc(CCodingContext *pSC) +{ + Int kk; + //Adapt (pSC->m_pAdaptHuffCBPCY, FALSE); + AdaptDiscriminant (pSC->m_pAdaptHuffCBPCY); + AdaptDiscriminant (pSC->m_pAdaptHuffCBPCY1); + for (kk = 0; kk < CONTEXTX; kk++) { /** adapt fixed code **/ + AdaptDiscriminant (pSC->m_pAHexpt[kk + CONTEXTX + CTDC]); + } +} + +/************************************************************************* + Experimental code -- encodeBlock + SR = <0 1 2> == + alphabet 12: + pAHexpt[0] == + alphabet 6: + pAHexpt[1] == + pAHexpt[2] == + alphabet 4: + pAHexpt[3] == (SR may be last or insignificant only) + alphabet f(run) (this can be extended to 6 contexts - SL and SR') + pAHexpt[4] == + alphabet f(lev) (this can be extended to 9 contexts) + pAHexpt[5-6] == first symbol + pAHexpt[7-8] == condition on SRn no use +*************************************************************************/ +#ifdef X86OPT_INLINE +__forceinline +#endif +static Void EncodeSignificantRun (Int iRun, Int iMaxRun, struct CAdaptiveHuffman *pAHexpt, BitIOInfo* pOut) +{ + Int iIndex, iFLC, iBin; + static const Int aIndex[] = { + 0,1,2,2,3,3,4,4,4,4,4,4,4,4, + 0,1,2,2,3,3,4,4,4,4,0,0,0,0, + 0,1,2,3,4,4 + }; + + if (iMaxRun < 5) { + //if (iMaxRun == 4) { + //static const Int gCode[] = { 0, 1, 1, 1 }; + static const Int gLen[] = { 3, 3, 2, 1 }; + if (iMaxRun > 1) + putBit16z(pOut, (iMaxRun != iRun), gLen[iMaxRun - iRun] - (4 - iMaxRun)); + //} + //else if (iMaxRun == 3) { + // if (iRun == 1) { + // putBit16z(pOut, 1, 1); + // } + // else { + // putBit16z(pOut, 3 ^ iRun, 2); + // } + //} + //else if (iMaxRun == 2) { + // putBit16z(pOut, 2 - iRun, 1); + //} + return; + } + + iBin = gSignificantRunBin[iMaxRun]; + iIndex = aIndex[iRun + iBin * 14 - 1]; + iFLC = gSignificantRunFixedLength[iIndex + iBin * 5]; + putBit16z(pOut, pAHexpt->m_pTable[iIndex * 2 + 1], pAHexpt->m_pTable[iIndex * 2 + 2]); + //this always uses table 0 + //pAHexpt->m_iDiscriminant += pAHexpt->m_pDelta[iIndex]; + putBit16(pOut, iRun + 1, iFLC); +} + +#ifdef X86OPT_INLINE +__forceinline +#endif +static Void EncodeFirstIndex (Bool bChroma, Int iLoc, Int iCont, Int iIndex, Int iSign, + struct CAdaptiveHuffman **ppAHexpt, BitIOInfo* pOut) +{ + // Int iContext = iCont + 1 + bChroma * 3; + struct CAdaptiveHuffman *pAHexpt = ppAHexpt[bChroma * 3]; + UNREFERENCED_PARAMETER( iLoc ); + UNREFERENCED_PARAMETER( iCont ); + pAHexpt->m_iDiscriminant += pAHexpt->m_pDelta[iIndex]; + pAHexpt->m_iDiscriminant1 += pAHexpt->m_pDelta1[iIndex]; + putBit16z(pOut, pAHexpt->m_pTable[iIndex * 2 + 1] * 2 + iSign, pAHexpt->m_pTable[iIndex * 2 + 2] + 1); + return; +} + +#ifdef X86OPT_INLINE +__forceinline +#endif +static Void EncodeIndex (Bool bChroma, Int iLoc, Int iCont, Int iIndex, Int iSign, + struct CAdaptiveHuffman **ppAHexpt, BitIOInfo* pOut) +{ + Int iContext = iCont + 1 + bChroma * 3; + + if (iLoc < 15) { + struct CAdaptiveHuffman *pAHexpt = ppAHexpt[iContext]; + pAHexpt->m_iDiscriminant += pAHexpt->m_pDelta[iIndex]; + pAHexpt->m_iDiscriminant1 += pAHexpt->m_pDelta1[iIndex]; + putBit16z(pOut, pAHexpt->m_pTable[iIndex * 2 + 1] * 2 + iSign, pAHexpt->m_pTable[iIndex * 2 + 2] + 1); + } + else if (iLoc == 15) { + static const U32 gCode[] = { 0, 6, 2, 7 }; + static const U32 gLen[] = { 1, 3, 2, 3 }; + putBit16z(pOut, gCode[iIndex] * 2 + iSign, gLen[iIndex] + 1); + return; + } + else {//if (iLoc == 16) { + putBit16z(pOut, iIndex * 2 + iSign, 1 + 1); + return; + } +} + +#ifdef X86OPT_INLINE +__forceinline +#endif +static Int EncodeBlock (Bool bChroma, const Int *aLocalCoef, Int iNumNonzero, + struct CAdaptiveHuffman **pAHexpt, Int iContextOffset, + BitIOInfo* pOut, UInt iLocation) +{ + Int iSR, iSL, iSRn, iIndex, k, iCont, iLev; + + /** first symbol **/ + iLev = aLocalCoef[1]; + iSR = (aLocalCoef[0] == 0); + iSL = ((unsigned int) (iLev + 1) > 2U); + iSRn = 1; + if (iNumNonzero == 1) { + iSRn = 0; + } + else if (aLocalCoef[2] > 0) { + iSRn = 2; + } + iIndex = iSRn * 4 + iSL * 2 + iSR; + EncodeFirstIndex (bChroma, iLocation, 0, iIndex, (iLev < 0), pAHexpt + iContextOffset, pOut); + iCont = iSR & iSRn; + if (iSL) { + EncodeSignificantAbsLevel ((UInt)(abs(iLev) - 1), pAHexpt[6 + iContextOffset + iCont], pOut); + } + if (iSR == 0) { + EncodeSignificantRun (aLocalCoef[0], 15 - iLocation, pAHexpt[0], pOut); + } + iLocation += aLocalCoef[0] + 1; + + for (k = 1; k < iNumNonzero; k++) { + if (iSRn == 2) { + EncodeSignificantRun (aLocalCoef[k * 2], 15 - iLocation, pAHexpt[0], pOut); + } + iLocation += aLocalCoef[k * 2] + 1; + iSRn = 1; + if (k == iNumNonzero - 1) { + iSRn = 0; + } + else if (aLocalCoef[k * 2 + 2] > 0) { + iSRn = 2; + } + //iSL = (abs(aLocalCoef[k * 2 + 1]) > 1); + iLev = aLocalCoef[k * 2 + 1]; + iSL = ((unsigned int) (iLev + 1) > 2U); + iIndex = iSRn * 2 + iSL; + EncodeIndex (bChroma, iLocation, iCont, iIndex, (iLev < 0), pAHexpt + iContextOffset, pOut); + + iCont &= iSRn; /** big difference! **/ + if (iSL) { + EncodeSignificantAbsLevel ((UInt)(abs(iLev) - 1), pAHexpt[6 + iContextOffset + iCont], pOut); + } + //else { + // putBit16z(pOut, (iLev < 0), 1); + //} + } + + return ICERR_OK; +} + +/************************************************************************* + CodeCoeffs +*************************************************************************/ +#ifdef X86OPT_INLINE +__forceinline +#endif +static Int CodeCoeffs (CWMImageStrCodec * pSC, CCodingContext *pContext, + Int iMBX, Int iMBY, BitIOInfo* pIO, BitIOInfo* pIOFL) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (Int) pSC->m_param.cNumChannels; + const Int iPlanes = (cf == YUV_420 || cf == YUV_422) ? 1 : iChannels; + CWMIMBInfo * pMBInfo = &pSC->MBInfo; + CAdaptiveScan *pScan; + Int iBlock, iNBlocks = 4; + Int iSubblock, iIndex = 0; + Int i, k; + const Int iNumCoeffs = 16; + Int iModelBits = pContext->m_aModelAC.m_iFlcBits[0], iFlex = 0, iTrim = 0, iMask = 0; + Int aLaplacianMean[2] = { 0, 0}, *pLM = aLaplacianMean; + Bool bChroma = FALSE; + + UNREFERENCED_PARAMETER( iMBX ); + UNREFERENCED_PARAMETER( iMBY ); + + assert (iModelBits < 16); + if (pContext->m_iTrimFlexBits <= iModelBits && pSC->WMISCP.sbSubband != SB_NO_FLEXBITS) { + iTrim = pContext->m_iTrimFlexBits; + iFlex = iModelBits - pContext->m_iTrimFlexBits; + iMask = (1 << iFlex) - 1; + } + + if(pSC->WMISCP.sbSubband != SB_NO_FLEXBITS) + writeIS_L1(pSC, pIOFL); + + /** set scan arrays **/ + if (pMBInfo->iOrientation == 1) { + pScan = pContext->m_aScanVert; + } + else { + pScan = pContext->m_aScanHoriz; + } + + /** write out coefficients **/ + for (i = 0; i < iPlanes; i++) { + Int iPattern = pMBInfo->iCBP[i]; + + if (cf == YUV_420) { + iNBlocks = 6; + iPattern += (pMBInfo->iCBP[1] << 16) + (pMBInfo->iCBP[2] << 20); + } + else if (cf == YUV_422) { + iNBlocks = 8; + iPattern += (pMBInfo->iCBP[1] << 16) + (pMBInfo->iCBP[2] << 24); + } + + for (iBlock = iIndex = 0; iBlock < iNBlocks; iBlock++) { + writeIS_L2(pSC, pIO); + if (pIO != pIOFL) + writeIS_L2(pSC, pIOFL); + + for (iSubblock = 0; iSubblock < 4; iSubblock++, iPattern >>= 1, iIndex ++) { + const PixelI *pCoeffs = NULL; + + if(iBlock < 4){ + pCoeffs = pSC->pPlane[i] + blkOffset[iIndex]; + } + else if(cf == YUV_420){ + pCoeffs = pSC->pPlane[iBlock - 3] + blkOffsetUV[iSubblock]; + } + else if(cf == YUV_422){ + pCoeffs = pSC->pPlane[1 + ((iBlock - 4) >> 1)] + blkOffsetUV_422[(iBlock & 1) * 4 + iSubblock]; + } + + /** put AC bits **/ + + if ((iPattern & 1) == 0) { + if (iFlex) { + /** FLC only, all else is skipped **/ + for (k = 1; k < iNumCoeffs; k++) { + Int data = pCoeffs[dctIndex[0][k]]; + Int atdata = (abs(data) >> iTrim); + Int word = atdata & iMask, len = iFlex; + if (atdata) { + word += word + (data < 0); + len++; + } + putBit16z(pIOFL, word, len); + } + } + } + else { +// WARNING!!! interaction between lowpass coefficients and highpass scan ordering - may lead to break in decoding when model bits is nonzero! +// Fix is to use same scan order in model bits transmission, and defer update of scan order to end of block + /** collect coefficients **/ + Int aLocalCoef[32], iNumNonzero = 0; + Int aResidual[16]; + + iNumNonzero = AdaptiveScan (pCoeffs, aResidual, + pScan, iModelBits, iTrim, aLocalCoef, 16); + (*pLM) += iNumNonzero; + EncodeBlock (bChroma, aLocalCoef, iNumNonzero, pContext->m_pAHexpt, CTDC + CONTEXTX, pIO, 1); + + if (iFlex) { + for (k = 1; k < iNumCoeffs; k++) { + putBit16z(pIOFL, aResidual[dctIndex[0][k]] >> 1, iFlex + (aResidual[dctIndex[0][k]] & 1)); + } + } + } + } + if (iBlock == 3) { + iModelBits = pContext->m_aModelAC.m_iFlcBits[1]; + assert (iModelBits < 16); + pLM = aLaplacianMean + 1; + bChroma = TRUE; + iTrim = iFlex = iMask = 0; + if (pContext->m_iTrimFlexBits <= iModelBits && pSC->WMISCP.sbSubband != SB_NO_FLEXBITS) { + iTrim = pContext->m_iTrimFlexBits; + iFlex = iModelBits - iTrim; + iMask = (1 << iFlex) - 1; + } + } + } + } + + /** update model at end of MB **/ + UpdateModelMB (cf, iChannels, aLaplacianMean, &pContext->m_aModelAC); + + return ICERR_OK; +} + + +/************************************************************************* + CodeCBP +*************************************************************************/ +static Void CodeCBP (CWMImageStrCodec * pSC, CCodingContext *pContext, + Int iMBX, Int iMBY, BitIOInfo *pIO) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannel = (cf == NCOMPONENT || cf == CMYK) ? (Int) pSC->m_param.cNumChannels : 1; + Int iDiffCBPCY, iDiffCBPCU = 0, iDiffCBPCV = 0, iDY; + Int iBlock, i, k; + static const Int aNumOnes[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; + static const Int aTabLen[] = { 0, 2, 2, 2, 2, 2, 3, 2, 2, 3, 3, 2, 3, 2, 2, 0 }; + static const Int aTabCode[] = { 0, 0, 1, 0, 2, 1, 4, 3, 3, 5, 6, 2, 7, 1, 0, 0 }; + CAdaptiveHuffman *pAH; + Int iCount, iPattern, iCode, iCodeU = 0, iCodeV = 0; + + UNREFERENCED_PARAMETER( iMBX ); + UNREFERENCED_PARAMETER( iMBY ); + + predCBPEnc(pSC, pContext); + writeIS_L1(pSC, pIO); + + iDiffCBPCU = pSC->MBInfo.iDiffCBP[1]; + iDiffCBPCV = pSC->MBInfo.iDiffCBP[2]; + + for (i = 0; i < iChannel; i++) { + iDiffCBPCY = pSC->MBInfo.iDiffCBP[i]; + + if(cf == YUV_420){ // PackCBP420 + iDiffCBPCY = (iDiffCBPCY & 0xf) + ((iDiffCBPCU & 1) << 4) + ((iDiffCBPCV & 1) << 5) + + ((iDiffCBPCY & 0x00f0) << 2) + ((iDiffCBPCU & 2) << 9) + ((iDiffCBPCV & 2) << 10) + + ((iDiffCBPCY & 0x0f00) << 4) + ((iDiffCBPCU & 4) << 14) + ((iDiffCBPCV & 4) << 15) + + ((iDiffCBPCY & 0xf000) << 6) + ((iDiffCBPCU & 8) << 19) + ((iDiffCBPCV & 8) << 20); + } + else if(cf == YUV_422){// PackCBP422 + iDiffCBPCY = (iDiffCBPCY & 0xf) + ((iDiffCBPCU & 1) << 4) + ((iDiffCBPCU & 4) << 3) + + ((iDiffCBPCV & 1) << 6) + ((iDiffCBPCV & 4) << 5) + + ((iDiffCBPCY & 0x00f0) << 4) + ((iDiffCBPCU & 2) << 11) + ((iDiffCBPCU & 8) << 10) + + ((iDiffCBPCV & 2) << 13) + ((iDiffCBPCV & 8) << 12) + + ((iDiffCBPCY & 0x0f00) << 8) + ((iDiffCBPCU & 16) << 16) + ((iDiffCBPCU & 64) << 15) + + ((iDiffCBPCV & 16) << 18) + ((iDiffCBPCV & 64) << 17) + + ((iDiffCBPCY & 0xf000) << 12) + ((iDiffCBPCU & 32) << 23) + ((iDiffCBPCU & 128) << 22) + + ((iDiffCBPCV & 32) << 25) + ((iDiffCBPCV & 128) << 24); + } + + /** send CBPCY **/ + iPattern = 0; + iDY = iDiffCBPCY; + if (cf == YUV_444) { + iDY |= (iDiffCBPCU | iDiffCBPCV); + } + + for (iBlock = 0; iBlock < 4; iBlock++) { + if(cf == YUV_422) { + iPattern |= ((iDY & 0xff) != 0) * 0x10; + iDY >>= 8; + } + else if (cf == YUV_420) { + iPattern |= ((iDY & 0x3f) != 0) * 0x10; + iDY >>= 6; + } + else { + iPattern |= ((iDY & 0xf) != 0) * 0x10; + iDY >>= 4; + } + iPattern >>= 1; + } + + pAH = pContext->m_pAdaptHuffCBPCY1; + iCount = aNumOnes[iPattern]; + putBit16z(pIO, pAH->m_pTable[iCount * 2 + 1], pAH->m_pTable[iCount * 2 + 2]); + pAH->m_iDiscriminant += pAH->m_pDelta[iCount]; + if (aTabLen[iPattern]) { + putBit16z(pIO, aTabCode[iPattern], aTabLen[iPattern]); + } + + for (iBlock = 0; iBlock < 4; iBlock++) { + switch (cf) { + case YUV_444: + iCode = iDiffCBPCY & 0xf; + iCodeU = iDiffCBPCU & 0xf; + iCodeV = iDiffCBPCV & 0xf; + iCode |= ((iCodeU != 0) << 4); + iCode |= ((iCodeV != 0) << 5); + iDiffCBPCY >>= 4; + iDiffCBPCU >>= 4; + iDiffCBPCV >>= 4; + break; + + case YUV_422: + iCode = iDiffCBPCY & 0xff; + iDiffCBPCY >>= 8; + break; + + case YUV_420: + iCode = iDiffCBPCY & 0x3f; + iDiffCBPCY >>= 6; + break; + + default: + iCode = iDiffCBPCY & 0xf; + iDiffCBPCY >>= 4; + } + + if (iCode) { + static const Int gTab0[16] = { 0,1,1,2, 1,3,3,4, 1,3,3,4, 2,4,4,5 }; + static const Int gFL0[16] = { 0,2,2,1, 2,2,2,2, 2,2,2,2, 1,2,2,0 }; + static const Int gCode0[16] = { 0,0,1,0, 2,0,1,0, 3,2,3,1, 1,2,3,0 }; + int val, iChroma = (iCode >> 4); + iCode &= 0xf; + + if(cf == YUV_422) { + iCodeU = (iChroma & 3); + iCodeV = ((iChroma >> 2) & 3); + iChroma = (iCodeU == 0 ? 0 : 1); + if(iCodeV != 0) { + iChroma += 2; + } + } + + if (iChroma) { + if (gTab0[iCode] > 2) { + val = 8; + } + else { + val = gTab0[iCode] + 6 - 1; + } + } + else { + val = gTab0[iCode] - 1; + } + pAH = pContext->m_pAdaptHuffCBPCY; + putBit16z(pIO, pAH->m_pTable[val * 2 + 1], pAH->m_pTable[val * 2 + 2]); + pAH->m_iDiscriminant += pAH->m_pDelta[val]; + + if (iChroma) { + if (iChroma == 1) + putBit16z(pIO, 1, 1); + else + putBit16z(pIO, 3 - iChroma, 2); + } + if (val == 8) { + if (gTab0[iCode] == 3) { + putBit16z(pIO, 1, 1); + } + else { + putBit16z(pIO, 5 - gTab0[iCode], 2); + } + } + if (gFL0[iCode]) { + putBit16z(pIO, gCode0[iCode], gFL0[iCode]); + } + + if (cf == YUV_444) { + pAH = pContext->m_pAHexpt[1]; + iPattern = iCodeU; + for (k = 0; k < 2; k++) { + if (iPattern) { + iCount = aNumOnes[iPattern]; + iCount--; + putBit16z(pIO, pAH->m_pTable[iCount * 2 + 1], pAH->m_pTable[iCount * 2 + 2]); + if (aTabLen[iPattern]) { + putBit16z(pIO, aTabCode[iPattern], aTabLen[iPattern]); + } + } + iPattern = iCodeV; + } + } + else if (cf == YUV_422){ + iPattern = iCodeU; + for(k = 0; k < 2; k ++) { + if(iPattern) { + if (iPattern == 1) + putBit16z(pIO, 1, 1); + else { + putBit16z(pIO, 3 - iPattern, 2); + } + } + iPattern = iCodeV; + } + } + } + } + } +} + +/************************************************************************* + macroblock encode function using 4x4 transforms +*************************************************************************/ +Int EncodeMacroblockHighpass(CWMImageStrCodec * pSC, CCodingContext *pContext, Int iMBX, Int iMBY) +{ + BitIOInfo* pIO = pContext->m_pIOAC; + BitIOInfo* pIOFL = pContext->m_pIOFL; + + if((pSC->WMISCP.bfBitstreamFormat != SPATIAL) && (pSC->pTile[pSC->cTileColumn].cBitsHP > 0)) // MB-based HP QP index + encodeQPIndex(pIO, pSC->MBInfo.iQIndexHP, pSC->pTile[pSC->cTileColumn].cBitsHP); + + /** reset adaptive scan totals **/ + if (pSC->m_bResetRGITotals) { + Int iScale = 2; + Int iWeight = iScale * 16; + Int k; + pContext->m_aScanHoriz[0].uTotal = pContext->m_aScanVert[0].uTotal = MAXTOTAL; + for (k = 1; k < 16; k++) { + pContext->m_aScanHoriz[k].uTotal = pContext->m_aScanVert[k].uTotal = iWeight; + iWeight -= iScale; + } + } + CodeCBP(pSC, pContext, iMBX, iMBY, pIO); + if(CodeCoeffs(pSC, pContext, iMBX, iMBY, pIO, pIOFL) != ICERR_OK) + return ICERR_ERROR; + + if (pSC->m_bResetContext) { + AdaptHighpassEnc(pContext); + } + + return ICERR_OK; +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strFwdTransform.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strFwdTransform.c new file mode 100644 index 0000000..968e010 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strFwdTransform.c @@ -0,0 +1,1111 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strTransform.h" +#include "encode.h" + +/** rotation by pi/8 **/ +#define ROTATE1(a, b) (b) -= (((a) + 1) >> 1), (a) += (((b) + 1) >> 1) // this works well too +#define ROTATE2(a, b) (b) -= (((a)*3 + 4) >> 3), (a) += (((b)*3 + 4) >> 3) // this works well too + +/** local functions **/ +static Void fwdOddOdd(PixelI *, PixelI *, PixelI *, PixelI *); +static Void fwdOddOddPre(PixelI *, PixelI *, PixelI *, PixelI *); +static Void fwdOdd(PixelI *, PixelI *, PixelI *, PixelI *); +static Void strDCT2x2alt(PixelI * a, PixelI * b, PixelI * c, PixelI * d); +static Void strHSTenc1(PixelI *, PixelI *); +static Void strHSTenc(PixelI *, PixelI *, PixelI *, PixelI *); +static Void strHSTenc1_edge (PixelI *pa, PixelI *pd); + +//static Void scaleDownUp0(PixelI *, PixelI *); +//static Void scaleDownUp1(PixelI *, PixelI *); +//static Void scaleDownUp2(PixelI *, PixelI *); +//#define FOURBUTTERFLY_ENC_ALT(p, i00, i01, i02, i03, i10, i11, i12, i13, \ +// i20, i21, i22, i23, i30, i31, i32, i33) \ +// strHSTenc(&p[i00], &p[i01], &p[i02], &p[i03]); \ +// strHSTenc(&p[i10], &p[i11], &p[i12], &p[i13]); \ +// strHSTenc(&p[i20], &p[i21], &p[i22], &p[i23]); \ +// strHSTenc(&p[i30], &p[i31], &p[i32], &p[i33]); \ +// strHSTenc1(&p[i00], &p[i03]); \ +// strHSTenc1(&p[i10], &p[i13]); \ +// strHSTenc1(&p[i20], &p[i23]); \ +// strHSTenc1(&p[i30], &p[i33]) + +/** DCT stuff **/ +/** data order before DCT **/ +/** 0 1 2 3 **/ +/** 4 5 6 7 **/ +/** 8 9 10 11 **/ +/** 12 13 14 15 **/ +/** data order after DCT **/ +/** 0 8 4 6 **/ +/** 2 10 14 12 **/ +/** 1 11 15 13 **/ +/** 9 3 7 5 **/ +/** reordering should be combined with zigzag scan **/ + +Void strDCT4x4Stage1(PixelI * p) +{ + /** butterfly **/ + //FOURBUTTERFLY(p, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); + FOURBUTTERFLY_HARDCODED1(p); + + /** top left corner, butterfly => butterfly **/ + strDCT2x2up(&p[0], &p[1], &p[2], &p[3]); + + /** bottom right corner, pi/8 rotation => pi/8 rotation **/ + fwdOddOdd(&p[15], &p[14], &p[13], &p[12]); + + /** top right corner, butterfly => pi/8 rotation **/ + fwdOdd(&p[5], &p[4], &p[7], &p[6]); + + /** bottom left corner, pi/8 rotation => butterfly **/ + fwdOdd(&p[10], &p[8], &p[11], &p[9]); +} + +Void strDCT4x4SecondStage(PixelI * p) +{ + /** butterfly **/ + FOURBUTTERFLY(p, 0, 192, 48, 240, 64, 128, 112, 176,16, 208, 32, 224, 80, 144, 96, 160); + + /** top left corner, butterfly => butterfly **/ + strDCT2x2up(&p[0], &p[64], &p[16], &p[80]); + + /** bottom right corner, pi/8 rotation => pi/8 rotation **/ + fwdOddOdd(&p[160], &p[224], &p[176], &p[240]); + + /** top right corner, butterfly => pi/8 rotation **/ + fwdOdd(&p[128], &p[192], &p[144], &p[208]); + + /** bottom left corner, pi/8 rotation => butterfly **/ + fwdOdd(&p[32], &p[48], &p[96], &p[112]); +} + +Void strNormalizeEnc(PixelI* p, Bool bChroma) +{ + int i; + if (!bChroma) { + //for (i = 0; i < 256; i += 16) { + // p[i] = (p[i] + 1) >> 2; + //} + } + else { + for (i = 0; i < 256; i += 16) { + p[i] >>= 1; + } + } +} + +/** 2x2 DCT with pre-scaling - for use on encoder side **/ +Void strDCT2x2dnEnc(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, C, t; + a = (*pa + 0) >> 1; + b = (*pb + 0) >> 1; + C = (*pc + 0) >> 1; + d = (*pd + 0) >> 1; + //PixelI t1, t2; + + a += d; + b -= C; + t = ((a - b) >> 1); + c = t - d; + d = t - C; + a -= d; + b += c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +/** pre filter stuff **/ +/** 2-point pre for boundaries **/ +Void strPre2(PixelI * pa, PixelI * pb) +{ + PixelI a, b; + a = *pa; + b = *pb; + + /** rotate **/ + b -= ((a + 2) >> 2); + a -= ((b + 1) >> 1); + + a -= (b >> 5); + a -= (b >> 9); + a -= (b >> 13); + + b -= ((a + 2) >> 2); + + *pa = a; + *pb = b; +} + +Void strPre2x2(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + a += d; + b += c; + d -= (a + 1) >> 1; + c -= (b + 1) >> 1; + + /** rotate **/ + b -= ((a + 2) >> 2); + a -= ((b + 1) >> 1); + a -= (b >> 5); + a -= (b >> 9); + a -= (b >> 13); + b -= ((a + 2) >> 2); + + /** butterflies **/ + d += (a + 1) >> 1; + c += (b + 1) >> 1; + a -= d; + b -= c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +/** 4-point pre for boundaries **/ +Void strPre4(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + a += d, b += c; + d -= ((a + 1) >> 1), c -= ((b + 1) >> 1); + + ROTATE1(c, d); + + strHSTenc1_edge(&a, &d); strHSTenc1_edge(&b, &c); + + d += ((a + 1) >> 1), c += ((b + 1) >> 1); + a -= d, b -= c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +/***************************************************************************************** + Input data offsets: + (15)(14)|(10+64)(11+64) p0 (15)(14)|(74)(75) + (13)(12)|( 8+64)( 9+64) (13)(12)|(72)(73) + --------+-------------- --------+-------- + ( 5)( 4)|( 0+64) (1+64) p1 ( 5)( 4)|(64)(65) + ( 7)( 6)|( 2+64) (3+64) ( 7)( 6)|(66)(67) +*****************************************************************************************/ +Void strPre4x4Stage1Split(PixelI *p0, PixelI *p1, Int iOffset) +{ + PixelI *p2 = p0 + 72 - iOffset; + PixelI *p3 = p1 + 64 - iOffset; + p0 += 12; + p1 += 4; + + /** butterfly & scaling **/ + strHSTenc(p0 + 0, p2 + 0, p1 + 0, p3 + 0); + strHSTenc(p0 + 1, p2 + 1, p1 + 1, p3 + 1); + strHSTenc(p0 + 2, p2 + 2, p1 + 2, p3 + 2); + strHSTenc(p0 + 3, p2 + 3, p1 + 3, p3 + 3); + strHSTenc1(p0 + 0, p3 + 0); + strHSTenc1(p0 + 1, p3 + 1); + strHSTenc1(p0 + 2, p3 + 2); + strHSTenc1(p0 + 3, p3 + 3); + + /** anti diagonal corners: rotation by pi/8 **/ + ROTATE1(p1[2], p1[3]); + ROTATE1(p1[0], p1[1]); + ROTATE1(p2[1], p2[3]); + ROTATE1(p2[0], p2[2]); + + /** bottom right corner: pi/8 rotation => pi/8 rotation **/ + fwdOddOddPre(p3 + 0, p3 + 1, p3 + 2, p3 + 3); + + /** butterfly **/ + strDCT2x2dn(p0 + 0, p2 + 0, p1 + 0, p3 + 0); + strDCT2x2dn(p0 + 1, p2 + 1, p1 + 1, p3 + 1); + strDCT2x2dn(p0 + 2, p2 + 2, p1 + 2, p3 + 2); + strDCT2x2dn(p0 + 3, p2 + 3, p1 + 3, p3 + 3); +} + +Void strPre4x4Stage1(PixelI* p, Int iOffset) +{ + strPre4x4Stage1Split(p, p + 16, iOffset); +} + +/***************************************************************************************** + Input data offsets: + (15)(14)|(10+32)(11+32) p0 (15)(14)|(42)(43) + (13)(12)|( 8+32)( 9+32) (13)(12)|(40)(41) + --------+-------------- --------+-------- + ( 5)( 4)|( 0+32)( 1+32) p1 ( 5)( 4)|(32)(33) + ( 7)( 6)|( 2+32)( 3+32) ( 7)( 6)|(34)(35) +*****************************************************************************************/ +Void strPre4x4Stage2Split(PixelI* p0, PixelI* p1) +{ + /** butterfly **/ + strHSTenc(p0 - 96, p0 + 96, p1 - 112, p1 + 80); + strHSTenc(p0 - 32, p0 + 32, p1 - 48, p1 + 16); + strHSTenc(p0 - 80, p0 + 112, p1 - 128, p1 + 64); + strHSTenc(p0 - 16, p0 + 48, p1 - 64, p1 + 0); + strHSTenc1(p0 - 96, p1 + 80); + strHSTenc1(p0 - 32, p1 + 16); + strHSTenc1(p0 - 80, p1 + 64); + strHSTenc1(p0 - 16, p1 + 0); + + /** anti diagonal corners: rotation **/ + ROTATE1(p1[-48], p1[-112]); + ROTATE1(p1[-64], p1[-128]); + ROTATE1(p0[112], p0[ 96]); + ROTATE1(p0[ 48], p0[ 32]); + + /** bottom right corner: pi/8 rotation => pi/8 rotation **/ + fwdOddOddPre(p1 + 0, p1 + 64, p1 + 16, p1 + 80); + + /** butterfly **/ + strDCT2x2dn(p0 - 96, p1 - 112, p0 + 96, p1 + 80); + strDCT2x2dn(p0 - 32, p1 - 48, p0 + 32, p1 + 16); + strDCT2x2dn(p0 - 80, p1 - 128, p0 + 112, p1 + 64); + strDCT2x2dn(p0 - 16, p1 - 64, p0 + 48, p1 + 0); +} + + +/** + Hadamard+Scale transform + for some strange reason, breaking up the function into two blocks, strHSTenc1 and strHSTenc + seems to work faster +**/ +static Void strHSTenc(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + /** different realization : does rescaling as well! **/ + PixelI a, b, c, d; + a = *pa; + b = *pb; + d = *pc; + c = *pd; + + a += c; + b -= d; + c = ((a - b) >> 1) - c; + d += (b >> 1); + b += c; + + a -= (d * 3 + 4) >> 3; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +static Void strHSTenc1(PixelI *pa, PixelI *pd) +{ + /** different realization : does rescaling as well! **/ + PixelI a, d; + a = *pa; + d = *pd; + + d -= (a >> 7); + d += (a >> 10); + + //a -= (d * 3 + 4) >> 3; + d -= (a * 3 + 0) >> 4; + a -= (d * 3 + 0) >> 3; + d = (a >> 1) - d; + a -= d; + + *pa = a; + *pd = d; +} + +static Void strHSTenc1_edge (PixelI *pa, PixelI *pd) +{ + /** different realizion as compared to scaling operator for 2D case **/ + PixelI a, d; + a = *pa; + d = -(*pd); // Negative sign needed here for 1D scaling case to ensure correct scaling. + + a -= d; + d += (a >> 1); + a -= (d * 3 + 4) >> 3; + // End new operations + + //Scaling modification of adding 7/1024 in two steps (without multiplication by 7). + d -= (a >> 7); + d += (a >> 10); + + d -= (a * 3 + 0) >> 4; + a -= (d * 3 + 0) >> 3; + d = (a >> 1) - d; + a -= d; + + *pa = a; + *pd = d; +} + +/** Kron(Rotate(pi/8), Rotate(pi/8)) **/\ +static Void fwdOddOdd(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, t1, t2; + + a = *pa; + b = -*pb; + c = -*pc; + d = *pd; + + /** butterflies **/ + d += a; + c -= b; + a -= (t1 = d >> 1); + b += (t2 = c >> 1); + + /** rotate pi/4 **/ + a += (b * 3 + 4) >> 3; + b -= (a * 3 + 3) >> 2; + a += (b * 3 + 3) >> 3; + + /** butterflies **/ + b -= t2; + a += t1; + c += b; + d -= a; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} +/** Kron(Rotate(pi/8), Rotate(pi/8)) **/ +static Void fwdOddOddPre(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, t1, t2; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + d += a; + c -= b; + a -= (t1 = d >> 1); + b += (t2 = c >> 1); + + /** rotate pi/4 **/ + a += (b * 3 + 4) >> 3; + b -= (a * 3 + 2) >> 2; + a += (b * 3 + 6) >> 3; + + /** butterflies **/ + b -= t2; + a += t1; + c += b; + d -= a; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +/** Kron(Rotate(pi/8), [1 1; 1 -1]/sqrt(2)) **/ +/** [a b c d] => [D C A B] **/ +Void fwdOdd(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d; + a = *pa; + b = *pb; + c = *pc; + d = *pd; + + /** butterflies **/ + b -= c; + a += d; + c += (b + 1) >> 1; + d = ((a + 1) >> 1) - d; + + /** rotate pi/8 **/ + ROTATE2(a, b); + ROTATE2(c, d); + + /** butterflies **/ + d += (b) >> 1; + c -= (a + 1) >> 1; + b -= d; + a += c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +/************************************************************************* + Top-level function to tranform possible part of a macroblock +*************************************************************************/ +Void transformMacroblock(CWMImageStrCodec * pSC) +{ + OVERLAP olOverlap = pSC->WMISCP.olOverlap; + COLORFORMAT cfColorFormat = pSC->m_param.cfColorFormat; + Bool left = (pSC->cColumn == 0), right = (pSC->cColumn == pSC->cmbWidth); + Bool top = (pSC->cRow == 0), bottom = (pSC->cRow == pSC->cmbHeight); + Bool leftORright = (left || right), topORbottom = (top || bottom); + Bool topORleft = (left || top);// rightORbottom = (right || bottom); + Bool leftAdjacentColumn = (pSC->cColumn == 1), rightAdjacentColumn = (pSC->cColumn == pSC->cmbWidth - 1); + // Bool topAdjacentRow = (pSC->cRow == 1), bottomAdjacentRow = (pSC->cRow == pSC->cmbHeight - 1); + PixelI * p = NULL;// * pt = NULL; + Int i, j; + Int iNumChromaFullPlanes = (Int)((YUV_420 == cfColorFormat || YUV_422 == cfColorFormat) ? + 1 : pSC->m_param.cNumChannels); + +#define mbX pSC->mbX +#define mbY pSC->mbY +#define tileX pSC->tileX +#define tileY pSC->tileY +#define bVertTileBoundary pSC->bVertTileBoundary +#define bHoriTileBoundary pSC->bHoriTileBoundary +#define bOneMBLeftVertTB pSC->bOneMBLeftVertTB +#define bOneMBRightVertTB pSC->bOneMBRightVertTB +#define iPredBefore pSC->iPredBefore +#define iPredAfter pSC->iPredAfter + + if (pSC->WMISCP.bUseHardTileBoundaries) { + //Add tile location information + if (pSC->cColumn == 0) { + bVertTileBoundary = FALSE; + tileY = 0; + } + bOneMBLeftVertTB = bOneMBRightVertTB = FALSE; + if(tileY > 0 && tileY <= pSC->WMISCP.cNumOfSliceMinus1H && (pSC->cColumn - 1) == pSC->WMISCP.uiTileY[tileY]) + bOneMBRightVertTB = TRUE; + if(tileY < pSC->WMISCP.cNumOfSliceMinus1H && pSC->cColumn == pSC->WMISCP.uiTileY[tileY + 1]) { + bVertTileBoundary = TRUE; + tileY++; + } + else + bVertTileBoundary = FALSE; + if(tileY < pSC->WMISCP.cNumOfSliceMinus1H && (pSC->cColumn + 1) == pSC->WMISCP.uiTileY[tileY + 1]) + bOneMBLeftVertTB = TRUE; + + if (pSC->cRow == 0) { + bHoriTileBoundary = FALSE; + tileX = 0; + } + else if(mbY != pSC->cRow && tileX < pSC->WMISCP.cNumOfSliceMinus1V && pSC->cRow == pSC->WMISCP.uiTileX[tileX + 1]) { + bHoriTileBoundary = TRUE; + tileX++; + } + else if(mbY != pSC->cRow) + bHoriTileBoundary = FALSE; + } + else { + bVertTileBoundary = FALSE; + bHoriTileBoundary = FALSE; + bOneMBLeftVertTB = FALSE; + bOneMBRightVertTB = FALSE; + } + mbX = pSC->cColumn, mbY = pSC->cRow; + + //================================================================ + // 400_Y, 444_YUV + for(i = 0; i < iNumChromaFullPlanes; ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[i];//(0 == i ? pSC->pY0 : (1 == i ? pSC->pU0 : pSC->pV0)); + PixelI* const p1 = pSC->p1MBbuffer[i];//(0 == i ? pSC->pY1 : (1 == i ? pSC->pU1 : pSC->pV1)); + + //================================ + // first level overlap + if(OL_NONE != olOverlap) + { + /* Corner operations */ + if ((top || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPre4(p1 + 0, p1 + 1, p1 + 2, p1 + 3); + if ((top || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPre4(p1 - 59, p1 - 60, p1 - 57, p1 - 58); + if ((bottom || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPre4(p0 + 48 + 10, p0 + 48 + 11, p0 + 48 + 8, p0 + 48 + 9); + if ((bottom || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPre4(p0 - 1, p0 - 2, p0 - 3, p0 - 4); + if(!right && !bottom) + { + if (top || bHoriTileBoundary) + { + + for (j = ((left || bVertTileBoundary) ? 0 : -64); j < 192; j += 64) + { + p = p1 + j; + strPre4(p + 5, p + 4, p + 64, p + 65); + strPre4(p + 7, p + 6, p + 66, p + 67); + p = NULL; + } + } + else + { + for (j = ((left || bVertTileBoundary) ? 0 : -64); j < 192; j += 64) + { + strPre4x4Stage1Split(p0 + 48 + j, p1 + j, 0); + } + } + + if (left || bVertTileBoundary) + { + if (!top && !bHoriTileBoundary) + { + strPre4(p0 + 58, p0 + 56, p1 + 0, p1 + 2); + strPre4(p0 + 59, p0 + 57, p1 + 1, p1 + 3); + } + + for (j = -64; j < -16; j += 16) + { + p = p1 + j; + strPre4(p + 74, p + 72, p + 80, p + 82); + strPre4(p + 75, p + 73, p + 81, p + 83); + p = NULL; + } + } + else + { + for (j = -64; j < -16; j += 16) + { + strPre4x4Stage1(p1 + j, 0); + } + } + + strPre4x4Stage1(p1 + 0, 0); + strPre4x4Stage1(p1 + 16, 0); + strPre4x4Stage1(p1 + 32, 0); + strPre4x4Stage1(p1 + 64, 0); + strPre4x4Stage1(p1 + 80, 0); + strPre4x4Stage1(p1 + 96, 0); + strPre4x4Stage1(p1 + 128, 0); + strPre4x4Stage1(p1 + 144, 0); + strPre4x4Stage1(p1 + 160, 0); + } + + if (bottom || bHoriTileBoundary) + { + for (j = ((left || bVertTileBoundary) ? 48 : -16); j < (right ? -16 : 240); j += 64) + { + p = p0 + j; + strPre4(p + 15, p + 14, p + 74, p + 75); + strPre4(p + 13, p + 12, p + 72, p + 73); + p = NULL; + } + } + + if ((right || bVertTileBoundary) && !bottom) + { + if (!top && !bHoriTileBoundary) + { + strPre4(p0 - 1, p0 - 3, p1 - 59, p1 - 57); + strPre4(p0 - 2, p0 - 4, p1 - 60, p1 - 58); + } + for (j = -64; j < -16; j += 16) + { + p = p1 + j; + strPre4(p + 15, p + 13, p + 21, p + 23); + strPre4(p + 14, p + 12, p + 20, p + 22); + p = NULL; + } + } + } + + //================================ + // first level transform + if (!top) + { + for (j = (left ? 48 : -16); j < (right ? 48 : 240); j += 64) + { + strDCT4x4Stage1(p0 + j); + } + } + + if (!bottom) + { + for (j = (left ? 0 : -64); j < (right ? 0 : 192); j += 64) + { + strDCT4x4Stage1(p1 + j + 0); + strDCT4x4Stage1(p1 + j + 16); + strDCT4x4Stage1(p1 + j + 32); + } + } + + //================================ + // second level overlap + if (OL_TWO == olOverlap) + { + /* Corner operations */ + if ((top || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPre4(p1 + 0, p1 + 64, p1 + 0 + 16, p1 + 64 + 16); + if ((top || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPre4(p1 - 128, p1 - 64, p1 - 128 + 16, p1 - 64 + 16); + if ((bottom || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPre4(p0 + 32, p0 + 96, p0 + 32 + 16, p0 + 96 + 16); + if ((bottom || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPre4(p0 - 96, p0 - 32, p0 - 96 + 16, p0 - 32 + 16); + if ((leftORright || bVertTileBoundary) && (!topORbottom && !bHoriTileBoundary)) + { + if (left || bVertTileBoundary) { + j = 0; + strPre4(p0 + j + 32, p0 + j + 48, p1 + j + 0, p1 + j + 16); + strPre4(p0 + j + 96, p0 + j + 112, p1 + j + 64, p1 + j + 80); + } + if (right || bVertTileBoundary) { + j = -128; + strPre4(p0 + j + 32, p0 + j + 48, p1 + j + 0, p1 + j + 16); + strPre4(p0 + j + 96, p0 + j + 112, p1 + j + 64, p1 + j + 80); + } + } + + if (!leftORright && !bVertTileBoundary) + { + if (topORbottom || bHoriTileBoundary) + { + if (top || bHoriTileBoundary) { + p = p1; + strPre4(p - 128, p - 64, p + 0, p + 64); + strPre4(p - 112, p - 48, p + 16, p + 80); + p = NULL; + } + if (bottom || bHoriTileBoundary) { + p = p0 + 32; + strPre4(p - 128, p - 64, p + 0, p + 64); + strPre4(p - 112, p - 48, p + 16, p + 80); + p = NULL; + } + } + else + { + strPre4x4Stage2Split(p0, p1); + } + } + } + + //================================ + // second level transform + if (!topORleft){ + if (pSC->m_param.bScaledArith) { + strNormalizeEnc(p0 - 256, (i != 0)); + } + strDCT4x4SecondStage(p0 - 256); + } + } + + //================================================================ + // 420_UV + for(i = 0; i < (YUV_420 == cfColorFormat? 2 : 0); ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[1 + i];//(0 == i ? pSC->pU0 : pSC->pV0); + PixelI* const p1 = pSC->p1MBbuffer[1 + i];//(0 == i ? pSC->pU1 : pSC->pV1); + + //================================ + // first level overlap (420_UV) + if (OL_NONE != olOverlap) + { + /* Corner operations */ + if ((top || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPre4(p1 + 0, p1 + 1, p1 + 2, p1 + 3); + if ((top || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPre4(p1 - 27, p1 - 28, p1 - 25, p1 - 26); + if ((bottom || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPre4(p0 + 16 + 10, p0 + 16 + 11, p0 + 16 + 8, p0 + 16 + 9); + if ((bottom || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPre4(p0 - 1, p0 - 2, p0 - 3, p0 - 4); + if(!right && !bottom) + { + if (top || bHoriTileBoundary) + { + + for (j = ((left || bVertTileBoundary) ? 0 : -32); j < 32; j += 32) + { + p = p1 + j; + strPre4(p + 5, p + 4, p + 32, p + 33); + strPre4(p + 7, p + 6, p + 34, p + 35); + p = NULL; + } + } + else + { + for (j = ((left || bVertTileBoundary) ? 0: -32); j < 32; j += 32) + { + strPre4x4Stage1Split(p0 + 16 + j, p1 + j, 32); + } + } + + if (left || bVertTileBoundary) + { + if (!top && !bHoriTileBoundary) + { + strPre4(p0 + 26, p0 + 24, p1 + 0, p1 + 2); + strPre4(p0 + 27, p0 + 25, p1 + 1, p1 + 3); + } + + strPre4(p1 + 10, p1 + 8, p1 + 16, p1 + 18); + strPre4(p1 + 11, p1 + 9, p1 + 17, p1 + 19); + } + else if (!bVertTileBoundary) + { + strPre4x4Stage1(p1 - 32, 32); + } + + strPre4x4Stage1(p1, 32); + } + + if (bottom || bHoriTileBoundary) + { + for (j = ((left || bVertTileBoundary) ? 16: -16); j < (right ? -16: 32); j += 32) + { + p = p0 + j; + strPre4(p + 15, p + 14, p + 42, p + 43); + strPre4(p + 13, p + 12, p + 40, p + 41); + p = NULL; + } + } + + if ((right || bVertTileBoundary) && !bottom) + { + if (!top && !bHoriTileBoundary) + { + strPre4(p0 - 1, p0 - 3, p1 - 27, p1 - 25); + strPre4(p0 - 2, p0 - 4, p1 - 28, p1 - 26); + } + + strPre4(p1 - 17, p1 - 19, p1 - 11, p1 - 9); + strPre4(p1 - 18, p1 - 20, p1 - 12, p1 - 10); + } + } + + //================================ + // first level transform (420_UV) + if (!top) + { + for (j = (left ? 16 : -16); j < (right ? 16 : 48); j += 32) + { + strDCT4x4Stage1(p0 + j); + } + } + + if (!bottom) + { + for (j = (left ? 0 : -32); j < (right ? 0 : 32); j += 32) + { + strDCT4x4Stage1(p1 + j); + } + } + + //================================ + // second level overlap (420_UV) + if (OL_TWO == olOverlap) + { + if ((leftAdjacentColumn || bOneMBRightVertTB) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p1 - 64 + 0, *(p1 - 64 + 32)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (top || bHoriTileBoundary)) + iPredBefore[i][0] = *(p1 + 0); + if ((right || bVertTileBoundary) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p1 - 64 + 32, iPredBefore[i][0]); + + if ((leftAdjacentColumn || bOneMBRightVertTB) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p0 - 64 + 16, *(p0 - 64 + 48)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (bottom || bHoriTileBoundary)) + iPredBefore[i][1] = *(p0 + 16); + if ((right || bVertTileBoundary) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p0 - 64 + 48, iPredBefore[i][1]); + + if ((leftORright || bVertTileBoundary) && !topORbottom && !bHoriTileBoundary) + { + if (left || bVertTileBoundary) + strPre2(p0 + 0 + 16, p1 + 0); + if (right || bVertTileBoundary) + strPre2(p0 + -32 + 16, p1 + -32); + } + + if (!leftORright) + { + if ((topORbottom || bHoriTileBoundary) && !bVertTileBoundary) + { + if (top || bHoriTileBoundary) + strPre2(p1 - 32, p1); + if (bottom || bHoriTileBoundary) + strPre2(p0 + 16 - 32, p0 + 16); + } + else if (!topORbottom && !bHoriTileBoundary && !bVertTileBoundary) + strPre2x2(p0 - 16, p0 + 16, p1 - 32, p1); + } + if ((leftAdjacentColumn || bOneMBRightVertTB) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p1 - 64 + 0, *(p1 - 64 + 32)); + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (top || bHoriTileBoundary)) + iPredAfter[i][0] = *(p1 + 0); + if ((right || bVertTileBoundary) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p1 - 64 + 32, iPredAfter[i][0]); + if ((leftAdjacentColumn || bOneMBRightVertTB) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p0 - 64 + 16, *(p0 - 64 + 48)); + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (bottom || bHoriTileBoundary)) + iPredAfter[i][1] = *(p0 + 16); + if ((right || bVertTileBoundary) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p0 - 64 + 48, iPredAfter[i][1]); + } + + //================================ + // second level transform (420_UV) + if (!topORleft) + { + if (!pSC->m_param.bScaledArith) { + strDCT2x2dn(p0 - 64, p0 - 32, p0 - 48, p0 - 16); + } + else { + strDCT2x2dnEnc(p0 - 64, p0 - 32, p0 - 48, p0 - 16); + } + } + } + + //================================================================ + // 422_UV + for(i = 0; i < (YUV_422 == cfColorFormat? 2 : 0); ++i) + { + PixelI* const p0 = pSC->p0MBbuffer[1 + i];//(0 == i ? pSC->pU0 : pSC->pV0); + PixelI* const p1 = pSC->p1MBbuffer[1 + i];//(0 == i ? pSC->pU1 : pSC->pV1); + + //================================ + // first level overlap (422_UV) + if (OL_NONE != olOverlap) + { + /* Corner operations */ + if ((top || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPre4(p1 + 0, p1 + 1, p1 + 2, p1 + 3); + if ((top || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPre4(p1 - 59, p1 - 60, p1 - 57, p1 - 58); + if ((bottom || bHoriTileBoundary) && (left || bVertTileBoundary)) + strPre4(p0 + 48 + 10, p0 + 48 + 11, p0 + 48 + 8, p0 + 48 + 9); + if ((bottom || bHoriTileBoundary) && (right || bVertTileBoundary)) + strPre4(p0 - 1, p0 - 2, p0 - 3, p0 - 4); + if(!right && !bottom) + { + if (top || bHoriTileBoundary) + { + + for (j = ((left || bVertTileBoundary) ? 0 : -64); j < 64; j += 64) + { + p = p1 + j; + strPre4(p + 5, p + 4, p + 64, p + 65); + strPre4(p + 7, p + 6, p + 66, p + 67); + p = NULL; + } + } + else + { + for (j = ((left || bVertTileBoundary) ? 0: -64); j < 64; j += 64) + { + strPre4x4Stage1Split(p0 + 48 + j, p1 + j, 0); + } + } + + if (left || bVertTileBoundary) + { + if (!top && !bHoriTileBoundary) + { + strPre4(p0 + 58, p0 + 56, p1 + 0, p1 + 2); + strPre4(p0 + 59, p0 + 57, p1 + 1, p1 + 3); + } + + for (j = 0; j < 48; j += 16) + { + p = p1 + j; + strPre4(p + 10, p + 8, p + 16, p + 18); + strPre4(p + 11, p + 9, p + 17, p + 19); + p = NULL; + } + } + else if (!bVertTileBoundary) + { + for (j = -64; j < -16; j += 16) + { + strPre4x4Stage1(p1 + j, 0); + } + } + + strPre4x4Stage1(p1 + 0, 0); + strPre4x4Stage1(p1 + 16, 0); + strPre4x4Stage1(p1 + 32, 0); + } + + if (bottom || bHoriTileBoundary) + { + for (j = ((left || bVertTileBoundary) ? 48: -16); j < (right ? -16: 112); j += 64) + { + p = p0 + j; + strPre4(p + 15, p + 14, p + 74, p + 75); + strPre4(p + 13, p + 12, p + 72, p + 73); + p = NULL; + } + } + + if ((right || bVertTileBoundary) && !bottom) + { + if (!top && !bHoriTileBoundary) + { + strPre4(p0 - 1, p0 - 3, p1 - 59, p1 - 57); + strPre4(p0 - 2, p0 - 4, p1 - 60, p1 - 58); + } + + for (j = -64; j < -16; j += 16) + { + p = p1 + j; + strPre4(p + 15, p + 13, p + 21, p + 23); + strPre4(p + 14, p + 12, p + 20, p + 22); + p = NULL; + } + } + } + + //================================ + // first level transform (422_UV) + if (!top) + { + for (j = (left ? 48 : -16); j < (right ? 48 : 112); j += 64) + { + strDCT4x4Stage1(p0 + j); + } + } + + if (!bottom) + { + for (j = (left ? 0 : -64); j < (right ? 0 : 64); j += 64) + { + strDCT4x4Stage1(p1 + j + 0); + strDCT4x4Stage1(p1 + j + 16); + strDCT4x4Stage1(p1 + j + 32); + } + } + + //================================ + // second level overlap (422_UV) + if (OL_TWO == olOverlap) + { + if ((leftAdjacentColumn || bOneMBRightVertTB) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p1 - 128 + 0, *(p1 - 128 + 64)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (top || bHoriTileBoundary)) + iPredBefore[i][0] = *(p1 + 0); + if ((right || bVertTileBoundary) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p1 - 128 + 64, iPredBefore[i][0]); + + if ((leftAdjacentColumn || bOneMBRightVertTB) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p0 - 128 + 48, *(p0 - 128 + 112)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (bottom || bHoriTileBoundary)) + iPredBefore[i][1] = *(p0 + 48); + if ((right || bVertTileBoundary) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_DIFF(p0 - 128 + 112, iPredBefore[i][1]); + + if (!bottom) + { + if (leftORright || bVertTileBoundary) + { + if (!top && !bHoriTileBoundary) + { + if (left || bVertTileBoundary) + strPre2(p0 + 48 + 0, p1 + 0); + + if (right || bVertTileBoundary) + strPre2(p0 + 48 + -64, p1 + -64); + } + + if (left || bVertTileBoundary) + strPre2(p1 + 16, p1 + 16 + 16); + + if (right || bVertTileBoundary) + strPre2(p1 + -48, p1 + -48 + 16); + } + + if (!leftORright && !bVertTileBoundary) + { + if (top || bHoriTileBoundary) + strPre2(p1 - 64, p1); + else + strPre2x2(p0 - 16, p0 + 48, p1 - 64, p1); + + strPre2x2(p1 - 48, p1 + 16, p1 - 32, p1 + 32); + } + } + + if ((bottom || bHoriTileBoundary) && (!leftORright && !bVertTileBoundary)) + strPre2(p0 - 16, p0 + 48); + + if ((leftAdjacentColumn || bOneMBRightVertTB) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p1 - 128 + 0, *(p1 - 128 + 64)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (top || bHoriTileBoundary)) + iPredAfter[i][0] = *(p1 + 0); + if ((right || bVertTileBoundary) && (top || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p1 - 128 + 64, iPredAfter[i][0]); + + if ((leftAdjacentColumn || bOneMBRightVertTB) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p0 - 128 + 48, *(p0 - 128 + 112)); + + if ((rightAdjacentColumn || bOneMBLeftVertTB) && (bottom || bHoriTileBoundary)) + iPredAfter[i][1] = *(p0 + 48); + if ((right || bVertTileBoundary) && (bottom || bHoriTileBoundary)) + COMPUTE_CORNER_PRED_ADD(p0 - 128 + 112, iPredAfter[i][1]); + } + + //================================ + // second level transform (422_UV) + if (!topORleft) + { + if (!pSC->m_param.bScaledArith) { + strDCT2x2dn(p0 - 128, p0 - 64, p0 - 112, p0 - 48); + strDCT2x2dn(p0 - 96, p0 - 32, p0 - 80, p0 - 16); + } + else { + strDCT2x2dnEnc(p0 - 128, p0 - 64, p0 - 112, p0 - 48); + strDCT2x2dnEnc(p0 - 96, p0 - 32, p0 - 80, p0 - 16); + } + + // 1D lossless HT + p0[- 96] -= p0[-128]; + p0[-128] += ((p0[-96] + 1) >> 1); + } + } + assert(NULL == p); +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strPredQuantEnc.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strPredQuantEnc.c new file mode 100644 index 0000000..f2ab001 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strPredQuantEnc.c @@ -0,0 +1,511 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strcodec.h" +#include "encode.h" + +I32 QUANT_Mulless(PixelI v, PixelI o, I32 r) +{ + const I32 m = v >> 31; + + assert(sizeof(PixelI) == sizeof(U32)); + return ((((v ^ m) - m + o) >> r) ^ m) - m; +} + +I32 MUL32HR(U32 a, U32 b, U32 r) +{ + return (I32)((U32)((U64)a * b >> 32) >> r); +} + +I32 QUANT(PixelI v, PixelI o, I32 man, I32 exp) +{ + const I32 m = v >> 31; + + assert(sizeof(PixelI) == sizeof(U32)); + return (MUL32HR((v ^ m) - m + o, man, exp) ^ m) - m; +} + +Int quantizeMacroblock(CWMImageStrCodec* pSC) +{ + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + CWMIMBInfo * pMBInfo = &pSC->MBInfo; + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + int iChannel, i, j; + + if(/*pSC->m_param.bScaledArith && */pSC->m_param.bTranscode == FALSE) + for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){ + const Bool bUV = (iChannel > 0 && (cf == YUV_444 || cf == YUV_422 || cf == YUV_420)); + const int iNumBlock = (bUV ? (cf == YUV_422 ? 8 : (cf == YUV_420 ? 4 : 16)) : 16); + const int * pOffset = (iNumBlock == 4 ? blkOffsetUV : (iNumBlock == 8 ? blkOffsetUV_422 : blkOffset)); + CWMIQuantizer * pQPDC = pTile->pQuantizerDC[iChannel]; + CWMIQuantizer * pQPLP = pTile->pQuantizerLP[iChannel] + pMBInfo->iQIndexLP; + CWMIQuantizer * pQPHP = pTile->pQuantizerHP[iChannel] + pMBInfo->iQIndexHP; + + for(j = 0; j < iNumBlock; j ++){ + PixelI * pData = pSC->pPlane[iChannel] + pOffset[j]; + + if(j == 0) // DC + pData[0] = (pQPDC->iMan == 0 ? QUANT_Mulless(pData[0], pQPDC->iOffset, pQPDC->iExp) : QUANT(pData[0], pQPDC->iOffset, pQPDC->iMan, pQPDC->iExp)); + else if(pSC->WMISCP.sbSubband != SB_DC_ONLY) // LP + pData[0] = (pQPLP->iMan == 0 ? QUANT_Mulless(pData[0], pQPLP->iOffset, pQPLP->iExp) : QUANT(pData[0], pQPLP->iOffset, pQPLP->iMan, pQPLP->iExp)); + + // quantize HP + if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS) + for(i = 1; i < 16; i ++) + pData[i] = (pQPHP->iMan == 0 ? QUANT_Mulless(pData[i], pQPHP->iOffset, pQPHP->iExp) : QUANT(pData[i], pQPHP->iOffset, pQPHP->iMan, pQPHP->iExp)); + } + } + + for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){ + I32 * pDC = pSC->MBInfo.iBlockDC[iChannel]; + PixelI * pData = pSC->pPlane[iChannel]; + + if(iChannel > 0 && cf == YUV_422){ + for(i = 0; i < 8; i ++){ + pDC[i] = pData[blkOffsetUV_422[i]]; + } + } + else if(iChannel > 0 && cf == YUV_420){ + for(i = 0; i < 4; i ++){ + pDC[i] = pData[blkOffsetUV[i]]; + } + } + else{ + for(i = 0; i < 16; i ++){ + pDC[i] = pData[dctIndex[2][i]]; + } + } + } + + return 0; +} + +/* frequency domain prediction */ +Void predMacroblockEnc(CWMImageStrCodec * pSC) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Int iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : (Int) pSC->m_param.cNumChannels; + size_t mbX = pSC->cColumn - 1;// mbY = pSC->cRow - 1; + CWMIMBInfo *pMBInfo = &(pSC->MBInfo); + Int iDCACPredMode = getDCACPredMode(pSC, mbX); + Int iDCPredMode = (iDCACPredMode & 0x3); + Int iADPredMode = (iDCACPredMode & 0xC); + Int iACPredMode = getACPredMode(pMBInfo, cf); + PixelI * pOrg, * pRef; + Int i, j, k; + + pMBInfo->iOrientation = 2 - iACPredMode; + + /* keep necessary info for future prediction */ + updatePredInfo(pSC, pMBInfo, mbX, cf); + + for(i = 0; i < iChannels; i ++){ + pOrg = pMBInfo->iBlockDC[i]; // current DC block + + /* DC prediction */ + if(iDCPredMode == 1){ // predict DC from top + pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC; + } + else if(iDCPredMode == 0){ // predict DC from left + pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC; + } + else if(iDCPredMode == 2){// predict DC from top&left + pOrg[0] -= ((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC) >> 1; + } + + /* AD prediction */ + if(iADPredMode == 4){// predict AD from top + pRef = (pSC->PredInfoPrevRow[i] + mbX)->piAD; + pOrg[4] -= pRef[3], pOrg[8] -= pRef[4], pOrg[12] -= pRef[5]; + } + else if(iADPredMode == 0){// predict AD from left + pRef = (pSC->PredInfo[i] + mbX - 1)->piAD; + pOrg[1] -= pRef[0], pOrg[2] -= pRef[1], pOrg[3] -= pRef[2]; + } + + pOrg = pSC->pPlane[i]; + /* AC prediction */ + if(iACPredMode == 1){ // predict from top + for(k = 0; k <= 192; k += 64){ + /* inside macroblock, in reverse order */ + for(j = 48; j > 0; j -= 16){ + pOrg[k + j + 10] -= pOrg[k + j + 10 - 16]; + pOrg[k + j + 2] -= pOrg[k + j + 2 - 16]; + pOrg[k + j + 9] -= pOrg[k + j + 9 - 16]; + } + } + } + else if(iACPredMode == 0){ // predict from left + for(k = 0; k < 64; k += 16){ + /* inside macroblock, in reverse order */ + for(j = 192; j > 0; j -= 64){ + pOrg[k + j + 5] -= pOrg[k + j + 5 - 64]; + pOrg[k + j + 1] -= pOrg[k + j + 1 - 64]; + pOrg[k + j + 6] -= pOrg[k + j + 6 - 64]; + } + } + } + } + + if(cf == YUV_420){ + for(i = 1; i < 3; i ++){ + pOrg = pMBInfo->iBlockDC[i]; // current DC block + + /* DC prediciton */ + if(iDCPredMode == 1){ // predict DC from top + pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC; + } + else if(iDCPredMode == 0){ // predict DC from left + pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC; + } + else if(iDCPredMode == 2){ // predict DC from top&left + pOrg[0] -= (((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC + 1) >> 1); + } + + /* AD prediction */ + if(iADPredMode == 4){// predict AD from top + pOrg[2] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[1]; + } + else if(iADPredMode == 0){// predict AD from left + pOrg[1] -= (pSC->PredInfo[i] + mbX - 1)->piAD[0]; + } + + pOrg = pSC->pPlane[i]; + /* AC prediction */ + if(iACPredMode == 1){ // predict from top + for(j = 16; j <= 48; j += 32){ + /* inside macroblock */ + pOrg[j + 10] -= pOrg[j + 10 - 16]; + pOrg[j + 2] -= pOrg[j + 2 - 16]; + pOrg[j + 9] -= pOrg[j + 9 - 16]; + } + } + else if(iACPredMode == 0){ // predict from left + for(j = 32; j <= 48; j += 16){ + /* inside macroblock */ + pOrg[j + 5] -= pOrg[j + 5 - 32]; + pOrg[j + 1] -= pOrg[j + 1 - 32]; + pOrg[j + 6] -= pOrg[j + 6 - 32]; + } + } + } + } + else if(cf == YUV_422){ + for(i = 1; i < 3; i ++){ + pOrg = pMBInfo->iBlockDC[i]; // current DC block + + /* DC prediciton */ + if(iDCPredMode == 1){ // predict DC from top + pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC; + } + else if(iDCPredMode == 0){ // predict DC from left + pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC; + } + else if(iDCPredMode == 2){ // predict DC from top&left + pOrg[0] -= (((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC + 1) >> 1); + } + + /* AD prediction */ + if(iADPredMode == 4){// predict AD from top + pOrg[4] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[4]; // AC of HT !!! + pOrg[6] -= pOrg[2]; + pOrg[2] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[3]; + } + else if(iADPredMode == 0){// predict AD from left + pOrg[4] -= (pSC->PredInfo[i] + mbX - 1)->piAD[4]; // AC of HT !!! + pOrg[1] -= (pSC->PredInfo[i] + mbX - 1)->piAD[0]; + pOrg[5] -= (pSC->PredInfo[i] + mbX - 1)->piAD[2]; + } + else if(iDCPredMode == 1){ + pOrg[6] -= pOrg[2]; + } + + pOrg = pSC->pPlane[i]; // current MB + /* AC prediction */ + if(iACPredMode == 1){ // predict from top + for(j = 48; j > 0; j -= 16){ + for(k = 0; k <= 64; k += 64){ + /* inside macroblock */ + pOrg[j + k + 10] -= pOrg[j + k + 10 - 16]; + pOrg[j + k + 2] -= pOrg[j + k + 2 - 16]; + pOrg[j + k + 9] -= pOrg[j + k + 9 - 16]; + } + } + } + else if(iACPredMode == 0){ // predict from left + for(j = 64; j <= 112; j += 16){ + /* inside macroblock */ + pOrg[j + 5] -= pOrg[j + 5 - 64]; + pOrg[j + 1] -= pOrg[j + 1 - 64]; + pOrg[j + 6] -= pOrg[j + 6 - 64]; + } + } + } + } +} + + +/* CBP prediction for 16 x 16 MB */ +/* block index */ +/* 0 1 4 5 */ +/* 2 3 6 7 */ +/* 8 9 12 13 */ +/* 10 11 14 15 */ + +static int NumOnes(int i) +{ + int retval = 0; + static const int g_Count[] = { 0,1,1,2, 1,2,2,3, 1,2,2,3, 2,3,3,4 }; + i = i & 0xffff; + while (i) { + retval += g_Count[i & 0xf]; + i >>= 4; + } + return retval; +} + +#define SATURATE32(x) if((unsigned int)(x + 16) >= 32) { if (x < 0) x = -16; else x = 15; } + +static Int predCBPCEnc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel) +{ + Int iPredCBP = 0, iRetval = 0; + Int iNOrig = NumOnes(iCBP), iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP); + + UNREFERENCED_PARAMETER( mbY ); + + /* only top left block pattern is predicted from neighbour */ + if(pSC->m_bCtxLeft) { + if (pSC->m_bCtxTop) { + iPredCBP = 1; + } + else { + Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP; + iPredCBP = (iTopCBP >> 10) & 1; // left: top(10) => 0 + } + } + else { + Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP; + iPredCBP = ((iLeftCBP >> 5) & 1); // left(5) => 0 + } + + iPredCBP |= (iCBP & 0x3300) << 2; // [8 9 12 13]->[10 11 14 15] + iPredCBP |= (iCBP & 0xcc) << 6; // [2 3 6 7]->[8 9 12 13] + iPredCBP |= (iCBP & 0x33) << 2; // [0 1 4 5]->[2 3 6 7] + iPredCBP |= (iCBP & 0x11) << 1; // [0 4]->[1 5] + iPredCBP |= (iCBP & 0x2) << 3; // [1]->[4] + + if (c) c = 1; + if (pModel->m_iState[c] == 0) { + iRetval = iPredCBP ^ iCBP; + } + else if (pModel->m_iState[c] == 1) { + iRetval = iCBP; + } + else { + iRetval = iCBP ^ 0xffff; + } + + pModel->m_iCount0[c] += iNOrig - iNDiff; + SATURATE32(pModel->m_iCount0[c]); + + pModel->m_iCount1[c] += 16 - iNOrig - iNDiff; + SATURATE32(pModel->m_iCount1[c]); + + if (pModel->m_iCount0[c] < 0) { + if (pModel->m_iCount0[c] < pModel->m_iCount1[c]) { + pModel->m_iState[c] = 1; + } + else { + pModel->m_iState[c] = 2; + } + } + else if (pModel->m_iCount1[c] < 0) { + pModel->m_iState[c] = 2; + } + else { + pModel->m_iState[c] = 0; + } + return iRetval; +} + +static Int predCBPC420Enc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel) +{ + Int iPredCBP = 0, iRetval = 0; + Int iNOrig = NumOnes(iCBP) * 4, iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP); + + UNREFERENCED_PARAMETER( mbY ); + + /* only top left block pattern is predicted from neighbour */ + if(pSC->m_bCtxLeft) { + if (pSC->m_bCtxTop) { + iPredCBP = 1; + } + else { + Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP; + iPredCBP = (iTopCBP >> 2) & 1; // left: top(2) => 0 + } + } + else { + Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP; + iPredCBP = ((iLeftCBP >> 1) & 1); // left(1) => 0 + } + + iPredCBP |= (iCBP & 0x1) << 1; // [0]->[1] + iPredCBP |= (iCBP & 0x3) << 2; // [0 1]->[2 3] + + if (pModel->m_iState[1] == 0) { + iRetval = iPredCBP ^ iCBP; + } + else if (pModel->m_iState[1] == 1) { + iRetval = iCBP; + } + else { + iRetval = iCBP ^ 0xf; + } + + pModel->m_iCount0[1] += iNOrig - iNDiff; + SATURATE32(pModel->m_iCount0[1]); + + pModel->m_iCount1[1] += 16 - iNOrig - iNDiff; + SATURATE32(pModel->m_iCount1[1]); + + if (pModel->m_iCount0[1] < 0) { + if (pModel->m_iCount0[1] < pModel->m_iCount1[1]) { + pModel->m_iState[1] = 1; + } + else { + pModel->m_iState[1] = 2; + } + } + else if (pModel->m_iCount1[1] < 0) { + pModel->m_iState[1] = 2; + } + else { + pModel->m_iState[1] = 0; + } + return iRetval; +} + +static Int predCBPC422Enc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel) +{ + Int iPredCBP = 0, iRetval = 0; + Int iNOrig = NumOnes(iCBP) * 2, iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP); + + UNREFERENCED_PARAMETER( mbY ); + + /* only top left block pattern is predicted from neighbour */ + if(pSC->m_bCtxLeft) { + if (pSC->m_bCtxTop) { + iPredCBP = 1; + } + else { + Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP; + iPredCBP = (iTopCBP >> 6) & 1; // left: top(6) => 0 + } + } + else { + Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP; + iPredCBP = ((iLeftCBP >> 1) & 1); // left(1) => 0 + } + + iPredCBP |= (iCBP & 0x1) << 1; // [0]->[1] + iPredCBP |= (iCBP & 0x3) << 2; // [0 1]->[2 3] + iPredCBP |= (iCBP & 0xc) << 2; // [2 3]->[4 5] + iPredCBP |= (iCBP & 0x30) << 2; // [4 5]->[6 7] + + if (pModel->m_iState[1] == 0) { + iRetval = iPredCBP ^ iCBP; + } + else if (pModel->m_iState[1] == 1) { + iRetval = iCBP; + } + else { + iRetval = iCBP ^ 0xff; + } + + pModel->m_iCount0[1] += iNOrig - iNDiff; + SATURATE32(pModel->m_iCount0[1]); + + pModel->m_iCount1[1] += 16 - iNOrig - iNDiff; + SATURATE32(pModel->m_iCount1[1]); + + if (pModel->m_iCount0[1] < 0) { + if (pModel->m_iCount0[1] < pModel->m_iCount1[1]) { + pModel->m_iState[1] = 1; + } + else { + pModel->m_iState[1] = 2; + } + } + else if (pModel->m_iCount1[1] < 0) { + pModel->m_iState[1] = 2; + } + else { + pModel->m_iState[1] = 0; + } + return iRetval; +} + +Void predCBPEnc(CWMImageStrCodec* pSC, CCodingContext *pContext) +{ + size_t mbX = pSC->cColumn - 1, mbY = pSC->cRow - 1; + CWMIMBInfo * pMBInfo = &(pSC->MBInfo); + int iChannel, i, j; + + for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const Bool bUV = (iChannel > 0); + const int iNumBlock = (bUV ? (cf == YUV_422 ? 8 : (cf == YUV_420 ? 4 : 16)) : 16); + const int * pOffset = (iNumBlock == 4 ? blkOffsetUV : (iNumBlock == 8 ? blkOffsetUV_422 : blkOffset)); + const Int threshold = (1 << pContext->m_aModelAC.m_iFlcBits[bUV ? 1 : 0]) - 1, threshold2 = threshold * 2 + 1; + Int iCBP = 0; + + for(j = 0; j < iNumBlock; j ++){ + PixelI * pData = pSC->pPlane[iChannel] + pOffset[j]; + for(i = 1; i < 16; i ++){ + if((unsigned int)(pData[i] + threshold) >= (unsigned int) threshold2){ // significant coeff + iCBP |= (1 << j); // update CBP + break; + } + } + } + + pMBInfo->iCBP[iChannel] = (pSC->PredInfo[iChannel] + mbX)->iCBP = iCBP; + + if(iNumBlock == 16){ + pMBInfo->iDiffCBP[iChannel] = predCBPCEnc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel); + } + else if(iNumBlock == 8){ + pSC->MBInfo.iDiffCBP[iChannel] = predCBPC422Enc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel); + } + else{ + pSC->MBInfo.iDiffCBP[iChannel] = predCBPC420Enc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel); + } + } +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strenc.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strenc.c new file mode 100644 index 0000000..f0703e9 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strenc.c @@ -0,0 +1,2370 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include "strcodec.h" +#include "encode.h" +#include "strTransform.h" +#include +#include "perfTimer.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +#ifdef ADI_SYS_OPT +extern char L1WW[]; +#endif + +#ifdef X86OPT_INLINE +#define _FORCEINLINE __forceinline +#else // X86OPT_INLINE +#define _FORCEINLINE +#endif // X86OPT_INLINE + +Int inputMBRow(CWMImageStrCodec *); + +#if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_ENC) || defined(WMP_OPT_TRFM_ENC) +void StrEncOpt(CWMImageStrCodec* pSC); +#endif // OPT defined + +#define MINIMUM_PACKET_LENGTH 4 // as long as packet header - skipped if data is not accessed (happens only for flexbits) + +Void writeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], BitIOInfo * pIO, U8 cChMode, size_t cChannel, size_t iPos) +{ + if(cChMode > 2) + cChMode = 2; + + if(cChannel > 1) + putBit16(pIO, cChMode, 2); // Channel mode + else + cChMode = 0; + + putBit16(pIO, pQuantizer[0][iPos].iIndex, 8); // Y + + if(cChMode == 1) // MIXED + putBit16(pIO, pQuantizer[1][iPos].iIndex, 8); // UV + else if(cChMode > 0){ // INDEPENDENT + size_t i; + + for(i = 1; i < cChannel; i ++) + putBit16(pIO, pQuantizer[i][iPos].iIndex, 8); // UV + } +} + +// packet header: 00000000 00000000 00000001 ?????xxx +// xxx: 000(spatial) 001(DC) 010(AD) 011(AC) 100(FL) 101-111(reserved) +// ?????: (iTileY * cNumOfSliceV + iTileX) +Void writePacketHeader(BitIOInfo * pIO, U8 ptPacketType, U8 pID) +{ + putBit16(pIO, 0, 8); + putBit16(pIO, 0, 8); + putBit16(pIO, 1, 8); + putBit16(pIO, (pID << 3) + (ptPacketType & 7), 8); +} + +Int writeTileHeaderDC(CWMImageStrCodec * pSC, BitIOInfo * pIO) +{ + size_t iTile, j = (pSC->m_pNextSC == NULL ? 1U : 2U); + + for(; j > 0; j --){ + if((pSC->m_param.uQPMode & 1) != 0){ // not DC uniform + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + size_t i; + + pTile->cChModeDC = (U8)(rand() & 3); // channel mode, just for concept proofing! + + if(pSC->cTileRow + pSC->cTileColumn == 0) // allocate DC QP info + for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++) + if(allocateQuantizer(pSC->pTile[iTile].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK) + return ICERR_ERROR; + + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + pTile->pQuantizerDC[i]->iIndex = (U8)((rand() & 0x2f) + 1); // QP indexes, just for concept proofing! + + formatQuantizer(pTile->pQuantizerDC, pTile->cChModeDC, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith); + + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + pTile->pQuantizerDC[i]->iOffset = (pTile->pQuantizerDC[i]->iQP >> 1); + + writeQuantizer(pTile->pQuantizerDC, pIO, pTile->cChModeDC, pSC->m_param.cNumChannels, 0); + } + + pSC = pSC->m_pNextSC; + } + + return ICERR_OK; +} + +Int writeTileHeaderLP(CWMImageStrCodec * pSC, BitIOInfo * pIO) +{ + size_t k = (pSC->m_pNextSC == NULL ? 1U : 2U); + + for(; k > 0; k --){ + if(pSC->WMISCP.sbSubband != SB_DC_ONLY && (pSC->m_param.uQPMode & 2) != 0){ // not LP uniform + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + U8 i, j; + + pTile->bUseDC = ((rand() & 1) == 0 ? TRUE : FALSE); // use DC quantizer? + putBit16(pIO, pTile->bUseDC == TRUE ? 1 : 0, 1); + pTile->cBitsLP = 0; + + pTile->cNumQPLP = (pTile->bUseDC == TRUE ? 1 : (U8)((rand() & 0xf) + 1)); // # of LP QPs + + if(pSC->cTileRow > 0) + freeQuantizer(pTile->pQuantizerLP); + + if(allocateQuantizer(pTile->pQuantizerLP, pSC->m_param.cNumChannels, pTile->cNumQPLP) != ICERR_OK) + return ICERR_ERROR; + + if(pTile->bUseDC == TRUE) + useDCQuantizer(pSC, pSC->cTileColumn); + else{ + putBit16(pIO, pTile->cNumQPLP - 1, 4); + + pTile->cBitsLP = dquantBits(pTile->cNumQPLP); + + for(i = 0; i < pTile->cNumQPLP; i ++){ + pTile->cChModeLP[i] = (U8)(rand() & 3); // channel mode, just for concept proofing! + + for(j = 0; j < pSC->m_param.cNumChannels; j ++) + pTile->pQuantizerLP[j][i].iIndex = (U8)((rand() & 0xfe) + 1); // QP indexes, just for concept proofing! + formatQuantizer(pTile->pQuantizerLP, pTile->cChModeLP[i], pSC->m_param.cNumChannels, i, TRUE, pSC->m_param.bScaledArith); + writeQuantizer(pTile->pQuantizerLP, pIO, pTile->cChModeLP[i], pSC->m_param.cNumChannels, i); + } + } + } + pSC = pSC->m_pNextSC; + } + + return ICERR_OK; +} + +Int writeTileHeaderHP(CWMImageStrCodec * pSC, BitIOInfo * pIO) +{ + size_t k = (pSC->m_pNextSC == NULL ? 1U : 2U); + + for(; k > 0; k --){ + if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS && (pSC->m_param.uQPMode & 4) != 0){ // not HP uniform + CWMITile * pTile = pSC->pTile + pSC->cTileColumn; + U8 i, j; + + pTile->bUseLP = ((rand() & 1) == 0 ? TRUE : FALSE); // use LP quantizer? + putBit16(pIO, pTile->bUseLP == TRUE ? 1 : 0, 1); + pTile->cBitsHP = 0; + + pTile->cNumQPHP = (pTile->bUseLP == TRUE ? pTile->cNumQPLP : (U8)((rand() & 0xf) + 1)); // # of LP QPs + + if(pSC->cTileRow > 0) + freeQuantizer(pTile->pQuantizerHP); + + if(allocateQuantizer(pTile->pQuantizerHP, pSC->m_param.cNumChannels, pTile->cNumQPHP) != ICERR_OK) + return ICERR_ERROR; + + if(pTile->bUseLP == TRUE) + useLPQuantizer(pSC, pTile->cNumQPHP, pSC->cTileColumn); + else{ + putBit16(pIO, pTile->cNumQPHP - 1, 4); + pTile->cBitsHP = dquantBits(pTile->cNumQPHP); + + for(i = 0; i < pTile->cNumQPHP; i ++){ + pTile->cChModeHP[i] = (U8)(rand() & 3); // channel mode, just for concept proofing! + + for(j = 0; j < pSC->m_param.cNumChannels; j ++) + pTile->pQuantizerHP[j][i].iIndex = (U8)((rand() & 0xfe) + 1); // QP indexes, just for concept proofing! + formatQuantizer(pTile->pQuantizerHP, pTile->cChModeHP[i], pSC->m_param.cNumChannels, i, FALSE, pSC->m_param.bScaledArith); + writeQuantizer(pTile->pQuantizerHP, pIO, pTile->cChModeHP[i], pSC->m_param.cNumChannels, i); + } + } + } + pSC = pSC->m_pNextSC; + } + + return ICERR_OK; +} + +Int encodeMB(CWMImageStrCodec * pSC, Int iMBX, Int iMBY) +{ + CCodingContext * pContext = &pSC->m_pCodingContext[pSC->cTileColumn]; + + if(pSC->m_bCtxLeft && pSC->m_bCtxTop && pSC->m_bSecondary == FALSE && pSC->m_param.bTranscode == FALSE){ // write packet headers + U8 pID = (U8)((pSC->cTileRow * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + pSC->cTileColumn) & 0x1F); + + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL) { + writePacketHeader(pContext->m_pIODC, 0, pID); + if (pSC->m_param.bTrimFlexbitsFlag) + putBit16(pContext->m_pIODC, pContext->m_iTrimFlexBits, 4); + writeTileHeaderDC(pSC, pContext->m_pIODC); + writeTileHeaderLP(pSC, pContext->m_pIODC); + writeTileHeaderHP(pSC, pContext->m_pIODC); + } + else{ + writePacketHeader(pContext->m_pIODC, 1, pID); + writeTileHeaderDC(pSC, pContext->m_pIODC); + if(pSC->cSB > 1){ + writePacketHeader(pContext->m_pIOLP, 2, pID); + writeTileHeaderLP(pSC, pContext->m_pIOLP); + } + if(pSC->cSB > 2){ + writePacketHeader(pContext->m_pIOAC, 3, pID); + writeTileHeaderHP(pSC, pContext->m_pIOAC); + } + if(pSC->cSB > 3) { + writePacketHeader(pContext->m_pIOFL, 4, pID); + if (pSC->m_param.bTrimFlexbitsFlag) + putBit16(pContext->m_pIOFL, pContext->m_iTrimFlexBits, 4); + } + } + } + + if(EncodeMacroblockDC(pSC, pContext, iMBX, iMBY) != ICERR_OK) + return ICERR_ERROR; + + if(pSC->WMISCP.sbSubband != SB_DC_ONLY) + if(EncodeMacroblockLowpass(pSC, pContext, iMBX, iMBY) != ICERR_OK) + return ICERR_ERROR; + + if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS) + if(EncodeMacroblockHighpass(pSC, pContext, iMBX, iMBY) != ICERR_OK) + return ICERR_ERROR; + + if(iMBX + 1 == (int) pSC->cmbWidth && (iMBY + 1 == (int) pSC->cmbHeight || + (pSC->cTileRow < pSC->WMISCP.cNumOfSliceMinus1H && iMBY == (int) pSC->WMISCP.uiTileY[pSC->cTileRow + 1] - 1))) + { // end of a horizontal slice + size_t k, l; + + // get sizes of each packet and update index table + if (pSC->m_pNextSC == NULL || pSC->m_bSecondary) { + for(k = 0; k < pSC->cNumBitIO; k ++){ + fillToByte(pSC->m_ppBitIO[k]); + pSC->ppWStream[k]->GetPos(pSC->ppWStream[k], &l); + pSC->pIndexTable[pSC->cNumBitIO * pSC->cTileRow + k] = l + getSizeWrite(pSC->m_ppBitIO[k]); // offset + } + } + + // reset coding contexts + if(iMBY + 1 != (int) pSC->cmbHeight){ + for(k = 0; k <= pSC->WMISCP.cNumOfSliceMinus1V; k ++) + ResetCodingContextEnc(&pSC->m_pCodingContext[k]); + } + } + + return ICERR_OK; +} + +/************************************************************************* + Top level function for processing a macroblock worth of input +*************************************************************************/ +Int processMacroblock(CWMImageStrCodec *pSC) +{ + Bool topORleft = (pSC->cColumn == 0 || pSC->cRow == 0); + ERR_CODE result = ICERR_OK; + size_t j, jend = (pSC->m_pNextSC != NULL); + + for (j = 0; j <= jend; j++) { + transformMacroblock(pSC); + if(!topORleft){ + getTilePos(pSC, (Int)pSC->cColumn - 1, (Int)pSC->cRow - 1); + if(jend){ + pSC->m_pNextSC->cTileRow = pSC->cTileRow; + pSC->m_pNextSC->cTileColumn = pSC->cTileColumn; + } + if ((result = encodeMB(pSC, (Int)pSC->cColumn - 1, (Int)pSC->cRow - 1)) != ICERR_OK) + return result; + } + + if (jend) { + pSC->m_pNextSC->cRow = pSC->cRow; + pSC->m_pNextSC->cColumn = pSC->cColumn; + pSC = pSC->m_pNextSC; + } + } + + return ICERR_OK; +} + +/************************************************************************* + forwardRGBE: forward conversion from RGBE to RGB +*************************************************************************/ +static _FORCEINLINE PixelI forwardRGBE (PixelI RGB, PixelI E) +{ + PixelI iResult = 0, iAppend = 1; + + if (E == 0) + return 0; + + assert (E!=0); + + E--; + while (((RGB & 0x80) == 0) && (E > 0)) { + RGB = (RGB << 1) + iAppend; + iAppend = 0; + E--; + } + + // result will always be one of 3 cases + // E RGB convert to + // 0 [0.x] [0 x] + // 0 [1.x] [1 x] + // e [1.x] [e+1 x] + if (E == 0) { + iResult = RGB; + } + else { + E++; + iResult = (RGB & 0x7f) + (E << 7); + } + + return iResult; +} + +/************************************************************************* + convert float-32 into float with (c, lm)!! +*************************************************************************/ +static _FORCEINLINE PixelI float2pixel (float f, const char _c, const unsigned char _lm) +{ + union uif + { + I32 i; + float f; + } x; + + PixelI _h, e, e1, m, s; + + if (f == 0) + { + _h = 0; + } + else + { + x.f = f; + + e = (x.i >> 23) & 0x000000ff;//here set e as e, not s! e includes s: [s e] 9 bits [31..23] + m = (x.i & 0x007fffff) | 0x800000; // actual mantissa, with normalizer + if (e == 0) { // denormal-land + m ^= 0x800000; // actual mantissa, removing normalizer + e++; // actual exponent -126 + } + + e1 = e - 127 + _c; // this is basically a division or quantization to a different exponent + // note: _c cannot be greater than 127, so e1 cannot be greater than e + //assert (_c <= 127); + if (e1 <= 1) { // denormal-land + if (e1 < 1) + m >>= (1 - e1); // shift mantissa right to make exponent 1 + e1 = 1; + if ((m & 0x800000) == 0) // if denormal, set e1 to zero else to 1 + e1 = 0; + } + m &= 0x007fffff; + + //for float-22: + _h = (e1 << _lm) + ((m + (1 << (23 - _lm - 1))) >> (23 - _lm));//take 23-bit m, shift (23-lm), get lm-bit m for float22 + s = ((PixelI) x.i) >> 31; + //padding to int-32: + _h = (_h ^ s) - s; + } + + return _h; +} + +/************************************************************************* + convert Half-16 to internal format, only need to handle sign bit +*************************************************************************/ +static _FORCEINLINE PixelI forwardHalf (PixelI hHalf) +{ + PixelI s; + s = hHalf >> 31; + hHalf = ((hHalf & 0x7fff) ^ s) - s; + return hHalf; +} + + +//================================================================ +// Color Conversion +// functions to get image data from input buffer +// this inlcudes necessary color conversion and boundary padding +//================================================================ +#define _CC(r, g, b) (b -= r, r += ((b + 1) >> 1) - g, g += ((r + 0) >> 1)) +#define _CC_CMYK(c, m, y, k) (y -= c, c += ((y + 1) >> 1) - m, m += (c >> 1) - k, k += ((m + 1) >> 1)) + +//================================================================ +// BitIOInfo init/term for encoding +const size_t MAX_MEMORY_SIZE_IN_WORDS = 64 << 20; // 1 << 20 \approx 1 million + +Int StrIOEncInit(CWMImageStrCodec* pSC) +{ + pSC->m_param.bIndexTable = !(pSC->WMISCP.bfBitstreamFormat == SPATIAL && pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V == 0); + if(allocateBitIOInfo(pSC) != ICERR_OK){ + return ICERR_ERROR; + } + + attachISWrite(pSC->pIOHeader, pSC->WMISCP.pWStream); + + if(pSC->cNumBitIO > 0){ + size_t i; +#if defined(_WINDOWS_) || defined(UNDER_CE) // tmpnam does not exist in VS2005 WinCE CRT + TCHAR szPath[MAX_PATH]; + DWORD cSize, j, k; +#endif + char * pFilename; + + pSC->ppWStream = (struct WMPStream **)malloc(pSC->cNumBitIO * sizeof(struct WMPStream *)); + if(pSC->ppWStream == NULL) return ICERR_ERROR; + memset(pSC->ppWStream, 0, pSC->cNumBitIO * sizeof(struct WMPStream *)); + + if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS) { +#ifdef _WINDOWS_ + pSC->ppTempFile = (TCHAR **)malloc(pSC->cNumBitIO * sizeof(TCHAR *)); + if(pSC->ppTempFile == NULL) return ICERR_ERROR; + memset(pSC->ppTempFile, 0, pSC->cNumBitIO * sizeof(TCHAR *)); +#else + pSC->ppTempFile = (char **)malloc(pSC->cNumBitIO * sizeof(char *)); + if(pSC->ppTempFile == NULL) return ICERR_ERROR; + memset(pSC->ppTempFile, 0, pSC->cNumBitIO * sizeof(char *)); +#endif + } + + for(i = 0; i < pSC->cNumBitIO; i ++){ + if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS) { +#if defined(_WINDOWS_) || defined(UNDER_CE) // tmpnam does not exist in VS2005 WinCE CRT + Bool bUnicode = sizeof(TCHAR) == 2; + pSC->ppTempFile[i] = (TCHAR *)malloc(MAX_PATH * sizeof(TCHAR)); + if(pSC->ppTempFile[i] == NULL) return ICERR_ERROR; + + pFilename = (char *)pSC->ppTempFile[i]; + + cSize = GetTempPath(MAX_PATH, szPath); + if(cSize == 0 || cSize >= MAX_PATH) + return ICERR_ERROR; + if(!GetTempFileName(szPath, TEXT("wdp"), 0, pSC->ppTempFile[i])) + return ICERR_ERROR; + + if(bUnicode){ // unicode file name + for(k = j = cSize = 0; cSize < MAX_PATH; cSize ++, j += 2){ + if(pSC->ppTempFile[i][cSize] == '\0') + break; + if(pFilename[j] != '\0') + pFilename[k ++] = pFilename[j]; + if(pFilename[j + 1] != '\0') + pFilename[k ++] = pFilename[j + 1]; + } + pFilename[cSize] = '\0'; + } + +#else //DPK needs to support ANSI + pSC->ppTempFile[i] = (char *)malloc(FILENAME_MAX * sizeof(char)); + if(pSC->ppTempFile[i] == NULL) return ICERR_ERROR; + + if ((pFilename = tmpnam(NULL)) == NULL) + return ICERR_ERROR; + strcpy(pSC->ppTempFile[i], pFilename); +#endif + if(CreateWS_File(pSC->ppWStream + i, pFilename, "w+b") != ICERR_OK) return ICERR_ERROR; + + } + else { + if(CreateWS_List(pSC->ppWStream + i) != ICERR_OK) return ICERR_ERROR; + } + attachISWrite(pSC->m_ppBitIO[i], pSC->ppWStream[i]); + } + } + + return ICERR_OK; +} + +#define PUTBITS putBit16 +/************************************************************************* + Write variable length byte aligned integer +*************************************************************************/ +static Void PutVLWordEsc(BitIOInfo* pIO, Int iEscape, size_t s) +{ + if (iEscape) { + assert(iEscape <= 0xff && iEscape > 0xfc); // fd,fe,ff are the only valid escapes + PUTBITS(pIO, iEscape, 8); + } + else if (s < 0xfb00) { + PUTBITS(pIO, (U32) s, 16); + } + else { + size_t t = s >> 16; + if ((t >> 16) == 0) { + PUTBITS(pIO, 0xfb, 8); + } + else { + t >>= 16; + PUTBITS(pIO, 0xfc, 8); + PUTBITS(pIO, (U32)(t >> 16) & 0xffff, 16); + PUTBITS(pIO, (U32) t & 0xffff, 16); + } + PUTBITS(pIO, (U32) t & 0xffff, 16); + PUTBITS(pIO, (U32) s & 0xffff, 16); + } +} + +/************************************************************************* + Write index table at start (null index table) +*************************************************************************/ +Int writeIndexTableNull(CWMImageStrCodec * pSC) +{ + if(pSC->cNumBitIO == 0){ + BitIOInfo* pIO = pSC->pIOHeader; + fillToByte(pIO); + + /* Profile / Level info */ + PutVLWordEsc(pIO, 0, 4); // 4 bytes + PUTBITS(pIO, 111, 8); // default profile idc + PUTBITS(pIO, 255, 8); // default level idc + PUTBITS(pIO, 1, 16); // LAST_FLAG + } + + return ICERR_OK; +} + +/************************************************************************* + Write index table +*************************************************************************/ +Int writeIndexTable(CWMImageStrCodec * pSC) +{ + if(pSC->cNumBitIO > 0){ + BitIOInfo* pIO = pSC->pIOHeader; + size_t *pTable = pSC->pIndexTable, iSize[4] = { 0 }; + I32 iEntry = (I32)pSC->cNumBitIO * (pSC->WMISCP.cNumOfSliceMinus1H + 1), i, k, l; + + // write index table header [0x0001] - 2 bytes + PUTBITS(pIO, 1, 16); + + for(i = pSC->WMISCP.cNumOfSliceMinus1H; i>= 0 && pSC->bTileExtraction == FALSE; i --){ + for(k = 0; k < (int)pSC->cNumBitIO; ){ + for(l = 0; l < (pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++, k ++) + { + if (i > 0) + pTable[pSC->cNumBitIO * i + k] -= pSC->pIndexTable[pSC->cNumBitIO * (i - 1) + k]; // packet length + iSize[l] += pTable[pSC->cNumBitIO * i + k]; + } + } + } + + iSize[3] = iSize[2] + iSize[1] + iSize[0]; + iSize[2] = iSize[1] + iSize[0]; + iSize[1] = iSize[0]; + iSize[0] = 0; + + for(i = 0; i < iEntry; ){ + for(l = 0; l < (pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++, i ++) + { + writeIS_L1(pSC, pIO); + PutVLWordEsc(pIO, (pTable[i] <= MINIMUM_PACKET_LENGTH) ? 0xff : 0, iSize[l]); + iSize[l] += (pTable[i] <= MINIMUM_PACKET_LENGTH) ? 0 : pTable[i]; + } + } + + writeIS_L1(pSC, pIO); + PutVLWordEsc(pIO, 0xff, 0); // escape to end + fillToByte(pIO); + } + + return ICERR_OK; +} + +Int copyTo(struct WMPStream * pSrc, struct WMPStream * pDst, size_t iBytes) +{ + char pData[PACKETLENGTH]; + + if (iBytes <= MINIMUM_PACKET_LENGTH){ + pSrc->Read(pSrc, pData, iBytes); + return ICERR_OK; + } + + while(iBytes > PACKETLENGTH){ + pSrc->Read(pSrc, pData, PACKETLENGTH); + pDst->Write(pDst, pData, PACKETLENGTH); + iBytes -= PACKETLENGTH; + } + pSrc->Read(pSrc, pData, iBytes); + pDst->Write(pDst, pData, iBytes); + + return ICERR_OK; +} + +Int StrIOEncTerm(CWMImageStrCodec* pSC) +{ + BitIOInfo * pIO = pSC->pIOHeader; + + fillToByte(pIO); + + if(pSC->WMISCP.bVerbose){ + U32 i, j; + + printf("\n%d horizontal tiles:\n", pSC->WMISCP.cNumOfSliceMinus1H + 1); + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1H; i ++){ + printf(" offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileY[i]); + } + + printf("\n%d vertical tiles:\n", pSC->WMISCP.cNumOfSliceMinus1V + 1); + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){ + printf(" offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileX[i]); + } + + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){ + printf("\nSpatial order bitstream\n"); + } + else{ + printf("\nFrequency order bitstream\n"); + } + + if(!pSC->m_param.bIndexTable){ + printf("\nstreaming mode, no index table.\n"); + } + else if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){ + for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){ + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){ + printf("bitstream size for tile (%d, %d): %d.\n", j, i, (int) pSC->pIndexTable[j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i]); + } + } + } + else{ + for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){ + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){ + size_t * p = &pSC->pIndexTable[(j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i) * 4]; + printf("bitstream size of (DC, LP, AC, FL) for tile (%d, %d): %d %d %d %d.\n", j, i, + (int) p[0], (int) p[1], (int) p[2], (int) p[3]); + } + } + } + } + + writeIndexTable(pSC); // write index table to the header + + detachISWrite(pSC, pIO); + + if(pSC->cNumBitIO > 0){ + size_t i, j, k, l; + struct WMPStream * pDst = pSC->WMISCP.pWStream; + size_t * pTable = pSC->pIndexTable; + + for(i = 0; i < pSC->cNumBitIO; i ++){ + detachISWrite(pSC, pSC->m_ppBitIO[i]); + } + + for(i = 0; i < pSC->cNumBitIO; i ++){ + pSC->ppWStream[i]->SetPos(pSC->ppWStream[i], 0); // seek back for read + } + + for(l = 0; l < (size_t)(pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++){ + for(i = 0, k = l; i <= pSC->WMISCP.cNumOfSliceMinus1H; i ++){ // loop through tiles + for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1V; j ++){ + + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL) + copyTo(pSC->ppWStream[j], pDst, pTable[k ++]); + else if (!pSC->WMISCP.bProgressiveMode){ + copyTo(pSC->ppWStream[j * pSC->cSB + 0], pDst, pTable[k ++]); + if(pSC->cSB > 1) + copyTo(pSC->ppWStream[j * pSC->cSB + 1], pDst, pTable[k ++]); + if(pSC->cSB > 2) + copyTo(pSC->ppWStream[j * pSC->cSB + 2], pDst, pTable[k ++]); + if(pSC->cSB > 3) + copyTo(pSC->ppWStream[j * pSC->cSB + 3], pDst, pTable[k ++]); + } + else{ + copyTo(pSC->ppWStream[j * pSC->cSB + l], pDst, pTable[k]); + k += pSC->cSB; + } + } + } + } + + if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS){ + for(i = 0; i < pSC->cNumBitIO; i ++){ + if(pSC->ppWStream && pSC->ppWStream[i]){ + if((*(pSC->ppWStream + i))->state.file.pFile){ + fclose((*(pSC->ppWStream + i))->state.file.pFile); +#ifdef _WINDOWS_ + if(DeleteFileA((LPCSTR)pSC->ppTempFile[i]) == 0) + return ICERR_ERROR; +#else + if (remove(pSC->ppTempFile[i]) == -1) + return ICERR_ERROR; +#endif + } + + if (*(pSC->ppWStream + i)) + free(*(pSC->ppWStream + i)); + } + if(pSC->ppTempFile){ + if(pSC->ppTempFile[i]) + free(pSC->ppTempFile[i]); + } + } + + if(pSC->ppTempFile) + free(pSC->ppTempFile); + } + else{ + for(i = 0; i < pSC->cNumBitIO; i ++){ + if(pSC->ppWStream && pSC->ppWStream[i]) + pSC->ppWStream[i]->Close(pSC->ppWStream + i); + } + } + + free(pSC->ppWStream); + + free(pSC->m_ppBitIO); + free(pSC->pIndexTable); + } + + return 0; +} + +/************************************************************************* + Write header of image plane +*************************************************************************/ +Int WriteImagePlaneHeader(CWMImageStrCodec * pSC) +{ + CWMImageInfo * pII = &pSC->WMII; + CWMIStrCodecParam * pSCP = &pSC->WMISCP; + BitIOInfo* pIO = pSC->pIOHeader; + + PUTBITS(pIO, (Int) pSC->m_param.cfColorFormat, 3); // internal color format + PUTBITS(pIO, (Int) pSC->m_param.bScaledArith, 1); // lossless mode + +// subbands + PUTBITS(pIO, (U32)pSCP->sbSubband, 4); + +// color parameters + switch (pSC->m_param.cfColorFormat) { + case YUV_420: + case YUV_422: + case YUV_444: + PUTBITS(pIO, 0, 4); + PUTBITS(pIO, 0, 4); + break; + case NCOMPONENT: + PUTBITS(pIO, (Int) pSC->m_param.cNumChannels - 1, 4); + PUTBITS(pIO, 0, 4); + break; + default: + break; + } + +// float and 32s additional parameters + switch (pII->bdBitDepth) { + case BD_16: + case BD_16S: + PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8); + break; + case BD_32: + case BD_32S: + if(pSCP->nLenMantissaOrShift == 0) + pSCP->nLenMantissaOrShift = 10;//default + PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8); + break; + case BD_32F: + if(pSCP->nLenMantissaOrShift == 0) + pSCP->nLenMantissaOrShift = 13;//default + PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8);//float conversion parameters + PUTBITS(pIO, pSCP->nExpBias, 8); + break; + default: + break; + } + + // quantization + PUTBITS(pIO, (pSC->m_param.uQPMode & 1) == 1 ? 0 : 1, 1); // DC frame uniform quantization? + if((pSC->m_param.uQPMode & 1) == 0) + writeQuantizer(pSC->pTile[0].pQuantizerDC, pIO, (pSC->m_param.uQPMode >> 3) & 3, pSC->m_param.cNumChannels, 0); + if(pSC->WMISCP.sbSubband != SB_DC_ONLY){ + PUTBITS(pIO, (pSC->m_param.uQPMode & 0x200) == 0 ? 1 : 0, 1); // use DC quantization? + if((pSC->m_param.uQPMode & 0x200) != 0){ + PUTBITS(pIO, (pSC->m_param.uQPMode & 2) == 2 ? 0 : 1, 1); // LP frame uniform quantization? + if((pSC->m_param.uQPMode & 2) == 0) + writeQuantizer(pSC->pTile[0].pQuantizerLP, pIO, (pSC->m_param.uQPMode >> 5) & 3, pSC->m_param.cNumChannels, 0); + } + + if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){ + PUTBITS(pIO, (pSC->m_param.uQPMode & 0x400) == 0 ? 1 : 0, 1); // use LP quantization? + if((pSC->m_param.uQPMode & 0x400) != 0){ + PUTBITS(pIO, (pSC->m_param.uQPMode & 4) == 4 ? 0 : 1, 1); // HP frame uniform quantization? + if((pSC->m_param.uQPMode & 4) == 0) + writeQuantizer(pSC->pTile[0].pQuantizerHP, pIO, (pSC->m_param.uQPMode >> 7) & 3, pSC->m_param.cNumChannels, 0); + } + } + } + + fillToByte(pIO); // remove this later + return ICERR_OK; +} + +/************************************************************************* + Write header to buffer +*************************************************************************/ +Int WriteWMIHeader(CWMImageStrCodec * pSC) +{ + CWMImageInfo * pII = &pSC->WMII; + CWMIStrCodecParam * pSCP = &pSC->WMISCP; + CCoreParameters * pCoreParam = &pSC->m_param; + BitIOInfo* pIO = pSC->pIOHeader; + U32 /*iSizeOfSize = 2,*/ i; + // temporary assignments / reserved words + // const Int HEADERSIZE = 0; + Bool bInscribed = FALSE; + Bool bAbbreviatedHeader = (((pII->cWidth + 15) / 16 > 255 || (pII->cHeight + 15) / 16 > 255) ? FALSE : TRUE); + + if(pCoreParam->bTranscode == FALSE) + pCoreParam->cExtraPixelsTop = pCoreParam->cExtraPixelsLeft = pCoreParam->cExtraPixelsRight = pCoreParam->cExtraPixelsBottom = 0; + + // num of extra boundary pixels due to compressed domain processing + bInscribed = (pCoreParam->cExtraPixelsTop || pCoreParam->cExtraPixelsLeft || pCoreParam->cExtraPixelsBottom || pCoreParam->cExtraPixelsRight); + +// 0 + /** signature **/ + for (i = 0; i < 8; PUTBITS(pSC->pIOHeader, gGDISignature[i++], 8)); + +// 8 + /** codec version and subversion **/ + PUTBITS(pIO, CODEC_VERSION, 4); // this should be changed to "profile" in RTM + if (pSC->WMISCP.bUseHardTileBoundaries) + PUTBITS(pIO, CODEC_SUBVERSION_NEWSCALING_HARD_TILES, 4); + else + PUTBITS(pIO, CODEC_SUBVERSION_NEWSCALING_SOFT_TILES, 4); + +// 9 primary parameters + PUTBITS(pIO, (pSCP->cNumOfSliceMinus1V || pSCP->cNumOfSliceMinus1H) ? 1 : 0, 1); // tiling present + PUTBITS(pIO, (Int) pSCP->bfBitstreamFormat, 1); // bitstream layout + PUTBITS(pIO, pII->oOrientation, 3); // m_iRotateFlip + PUTBITS(pIO, pSC->m_param.bIndexTable, 1); // index table present + PUTBITS(pIO, pSCP->olOverlap, 2); // overlap + +// 10 + PUTBITS(pIO, bAbbreviatedHeader, 1); // short words for size and tiles + PUTBITS(pIO, 1, 1); // long word length (use intelligence later) + PUTBITS(pIO, bInscribed, 1); // windowing + PUTBITS(pIO, pSC->m_param.bTrimFlexbitsFlag, 1); // trim flexbits flag sent + PUTBITS(pIO, 0, 1); // tile stretching parameters (not enabled) + PUTBITS(pIO, 0, 2); // reserved bits + PUTBITS(pIO, (Int) pSC->m_param.bAlphaChannel, 1); // alpha channel present + +// 11 - informational + PUTBITS(pIO, (Int) pII->cfColorFormat, 4); // source color format + if(BD_1 == pII->bdBitDepth && pSCP->bBlackWhite) + PUTBITS(pIO, (Int) BD_1alt, 4); // source bit depth + else + PUTBITS(pIO, (Int) pII->bdBitDepth, 4); // source bit depth + +// 12 - Variable length fields +// size + putBit32(pIO, (U32)(pII->cWidth - 1), bAbbreviatedHeader ? 16 : 32); + putBit32(pIO, (U32)(pII->cHeight - 1), bAbbreviatedHeader ? 16 : 32); + +// tiling + if (pSCP->cNumOfSliceMinus1V || pSCP->cNumOfSliceMinus1H) { + PUTBITS(pIO, pSCP->cNumOfSliceMinus1V, LOG_MAX_TILES); // # of vertical slices + PUTBITS(pIO, pSCP->cNumOfSliceMinus1H, LOG_MAX_TILES); // # of horizontal slices + } + +// tile sizes + for(i = 0; i < pSCP->cNumOfSliceMinus1V; i ++){ // width in MB of vertical slices, not needed for last slice! + PUTBITS(pIO, pSCP->uiTileX[i + 1] - pSCP->uiTileX[i], bAbbreviatedHeader ? 8 : 16); + } + for(i = 0; i < pSCP->cNumOfSliceMinus1H; i ++){ // width in MB of horizontal slices, not needed for last slice! + PUTBITS(pIO, pSCP->uiTileY[i + 1] - pSCP->uiTileY[i], bAbbreviatedHeader ? 8 : 16); + } + +// window due to compressed domain processing + if (bInscribed) { + PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsTop, 6); + PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsLeft, 6); + PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsBottom, 6); + PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsRight, 6); + } + fillToByte(pIO); // redundant + + // write image plane headers + WriteImagePlaneHeader(pSC); + + return ICERR_OK; +} + +// streaming codec init/term +Int StrEncInit(CWMImageStrCodec* pSC) +{ + COLORFORMAT cf = pSC->m_param.cfColorFormat; + COLORFORMAT cfE = pSC->WMII.cfColorFormat; + U16 iQPIndexY = 0, iQPIndexYLP = 0, iQPIndexYHP = 0; + U16 iQPIndexU = 0, iQPIndexULP = 0, iQPIndexUHP = 0; + U16 iQPIndexV = 0, iQPIndexVLP = 0, iQPIndexVHP = 0; + size_t i; + Bool b32bit = sizeof(size_t) == 4; + + /** color transcoding with resolution change **/ + pSC->m_bUVResolutionChange = (((cfE == CF_RGB || cfE == YUV_444 || cfE == CMYK || cfE == CF_RGBE) && + (cf == YUV_422 || cf == YUV_420)) + || (cfE == YUV_422 && cf == YUV_420)) && !pSC->WMISCP.bYUVData; + + if(pSC->m_bUVResolutionChange){ + size_t cSize = ((cfE == YUV_422 ? 128 : 256) + (cf == YUV_420 ? 32 : 0)) * pSC->cmbWidth + 256; + + if(b32bit){ // integer overlow/underflow check for 32-bit system + if(((pSC->cmbWidth >> 16) * ((cfE == YUV_422 ? 128 : 256) + (cf == YUV_420 ? 32 : 0))) & 0xffff0000) + return ICERR_ERROR; + if(cSize >= 0x3fffffff) + return ICERR_ERROR; + } + pSC->pResU = (PixelI *)malloc(cSize * sizeof(PixelI)); + pSC->pResV = (PixelI *)malloc(cSize * sizeof(PixelI)); + if(pSC->pResU == NULL || pSC->pResV == NULL){ + return ICERR_ERROR; + } + } + + pSC->cTileColumn = pSC->cTileRow = 0; + + if(allocateTileInfo(pSC) != ICERR_OK) + return ICERR_ERROR; + + if(pSC->m_param.bTranscode == FALSE){ + pSC->m_param.uQPMode = 0x150; // 101010 000 + // 000 == uniform (not per tile) DC, LP, HP + // 101010 == cChMode == 2 == independent (not same) DC, LP, HP + + /** lossless or Y component lossless condition: all subbands present, uniform quantization with QPIndex 1 **/ + pSC->m_param.bScaledArith = !((pSC->m_param.uQPMode & 7) == 0 && + 1 == pSC->WMISCP.uiDefaultQPIndex <= 1 && + pSC->WMISCP.sbSubband == SB_ALL && + pSC->m_bUVResolutionChange == FALSE) && + !pSC->WMISCP.bUnscaledArith; + if (BD_32 == pSC->WMII.bdBitDepth || BD_32S == pSC->WMII.bdBitDepth || BD_32F == pSC->WMII.bdBitDepth) { + pSC->m_param.bScaledArith = FALSE; + } + pSC->m_param.uQPMode |= 0x600; // don't use DC QP for LP, LP QP for HP + + // default QPs + iQPIndexY = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1? + pSC->WMISCP.uiDefaultQPIndexAlpha : pSC->WMISCP.uiDefaultQPIndex; + + // determine the U,V index + iQPIndexU = pSC->WMISCP.uiDefaultQPIndexU!=0? + pSC->WMISCP.uiDefaultQPIndexU: iQPIndexY; + iQPIndexV = pSC->WMISCP.uiDefaultQPIndexV!=0? + pSC->WMISCP.uiDefaultQPIndexV: iQPIndexY; + + // determine the QPIndexYLP + iQPIndexYLP = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1 ? + pSC->WMISCP.uiDefaultQPIndexAlpha : + (pSC->WMISCP.uiDefaultQPIndexYLP == 0 ? + pSC->WMISCP.uiDefaultQPIndex : pSC->WMISCP.uiDefaultQPIndexYLP); // default to QPIndex if not set + + // determine the QPIndexYHP + iQPIndexYHP = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1 ? + pSC->WMISCP.uiDefaultQPIndexAlpha : + (pSC->WMISCP.uiDefaultQPIndexYHP == 0 ? + pSC->WMISCP.uiDefaultQPIndex : pSC->WMISCP.uiDefaultQPIndexYHP); // default to QPIndex if not set + + // determine the U,V LP index + iQPIndexULP = pSC->WMISCP.uiDefaultQPIndexULP!=0? + pSC->WMISCP.uiDefaultQPIndexULP: iQPIndexU; + iQPIndexVLP = pSC->WMISCP.uiDefaultQPIndexVLP!=0? + pSC->WMISCP.uiDefaultQPIndexVLP: iQPIndexV; + + // determine the U,V HP index + iQPIndexUHP = pSC->WMISCP.uiDefaultQPIndexUHP!=0? + pSC->WMISCP.uiDefaultQPIndexUHP: iQPIndexU; + iQPIndexVHP = pSC->WMISCP.uiDefaultQPIndexVHP!=0? + pSC->WMISCP.uiDefaultQPIndexVHP: iQPIndexV; + + // clamp the QPIndex - 0 is lossless mode + if(iQPIndexY < 2) + iQPIndexY = 0; + if (iQPIndexYLP < 2) + iQPIndexYLP = 0; + if (iQPIndexYHP < 2) + iQPIndexYHP = 0; + if(iQPIndexU < 2) + iQPIndexU = 0; + if (iQPIndexULP < 2) + iQPIndexULP = 0; + if (iQPIndexUHP < 2) + iQPIndexUHP = 0; + if(iQPIndexV < 2) + iQPIndexV = 0; + if (iQPIndexVLP < 2) + iQPIndexVLP = 0; + if (iQPIndexVHP < 2) + iQPIndexVHP = 0; + } + + if((pSC->m_param.uQPMode & 1) == 0){ // DC frame uniform quantization + if(allocateQuantizer(pSC->pTile[0].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK) + return ICERR_ERROR; + setUniformQuantizer(pSC, 0); + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + if(pSC->m_param.bTranscode) + pSC->pTile[0].pQuantizerDC[i]->iIndex = pSC->m_param.uiQPIndexDC[i]; + else + pSC->pTile[0].pQuantizerDC[i]->iIndex = pSC->m_param.uiQPIndexDC[i] = (U8)(((i == 0 ? iQPIndexY : (i == 1) ? iQPIndexU: iQPIndexV)) & 0xff); + formatQuantizer(pSC->pTile[0].pQuantizerDC, (pSC->m_param.uQPMode >> 3) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith); + + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + pSC->pTile[0].pQuantizerDC[i]->iOffset = (pSC->pTile[0].pQuantizerDC[i]->iQP >> 1); + } + + if(pSC->WMISCP.sbSubband != SB_DC_ONLY){ + if((pSC->m_param.uQPMode & 2) == 0){ // LP frame uniform quantization + if(allocateQuantizer(pSC->pTile[0].pQuantizerLP, pSC->m_param.cNumChannels, 1) != ICERR_OK) + return ICERR_ERROR; + setUniformQuantizer(pSC, 1); + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + if(pSC->m_param.bTranscode) + pSC->pTile[0].pQuantizerLP[i]->iIndex = pSC->m_param.uiQPIndexLP[i]; + else + pSC->pTile[0].pQuantizerLP[i]->iIndex = pSC->m_param.uiQPIndexLP[i] = (U8)(((i == 0 ? iQPIndexYLP : (i == 1) ? iQPIndexULP: iQPIndexVLP)) & 0xff); + formatQuantizer(pSC->pTile[0].pQuantizerLP, (pSC->m_param.uQPMode >> 5) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith); + } + + if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){ + if((pSC->m_param.uQPMode & 4) == 0){ // HP frame uniform quantization + if(allocateQuantizer(pSC->pTile[0].pQuantizerHP, pSC->m_param.cNumChannels, 1) != ICERR_OK) + return ICERR_ERROR; + setUniformQuantizer(pSC, 2); + for(i = 0; i < pSC->m_param.cNumChannels; i ++) + if(pSC->m_param.bTranscode) + pSC->pTile[0].pQuantizerHP[i]->iIndex = pSC->m_param.uiQPIndexHP[i]; + else + pSC->pTile[0].pQuantizerHP[i]->iIndex = pSC->m_param.uiQPIndexHP[i] = (U8)(((i == 0 ? iQPIndexYHP : (i == 1) ? iQPIndexUHP: iQPIndexVHP)) & 0xff); + formatQuantizer(pSC->pTile[0].pQuantizerHP, (pSC->m_param.uQPMode >> 7) & 3, pSC->m_param.cNumChannels, 0, FALSE, pSC->m_param.bScaledArith); + } + } + } + + if(allocatePredInfo(pSC) != ICERR_OK){ + return ICERR_ERROR; + } + + if(pSC->WMISCP.cNumOfSliceMinus1V >= MAX_TILES || AllocateCodingContextEnc (pSC, pSC->WMISCP.cNumOfSliceMinus1V + 1, pSC->WMISCP.uiTrimFlexBits) != ICERR_OK){ + return ICERR_ERROR; + } + + if (pSC->m_bSecondary) { + pSC->pIOHeader = pSC->m_pNextSC->pIOHeader; + pSC->m_ppBitIO = pSC->m_pNextSC->m_ppBitIO; + pSC->cNumBitIO = pSC->m_pNextSC->cNumBitIO; + pSC->cSB = pSC->m_pNextSC->cSB; + pSC->ppWStream = pSC->m_pNextSC->ppWStream; + pSC->pIndexTable = pSC->m_pNextSC->pIndexTable; + setBitIOPointers(pSC); + } + else { + StrIOEncInit(pSC); + setBitIOPointers(pSC); + WriteWMIHeader(pSC); + } + + return ICERR_OK; +} + +static Int StrEncTerm(CTXSTRCODEC ctxSC) +{ + CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC; + size_t j, jend = (pSC->m_pNextSC != NULL); + + for (j = 0; j <= jend; j++) { + if (sizeof(*pSC) != pSC->cbStruct) { + return ICERR_ERROR; + } + + if(pSC->m_bUVResolutionChange){ + if(pSC->pResU != NULL) + free(pSC->pResU); + if(pSC->pResV != NULL) + free(pSC->pResV); + } + + freePredInfo(pSC); + + if (j == 0) + StrIOEncTerm(pSC); + + FreeCodingContextEnc(pSC); + + freeTileInfo(pSC); + + pSC->WMISCP.nExpBias -= 128; // reset + + pSC = pSC->m_pNextSC; + } + + return 0; +} + +U32 setUniformTiling(U32 * pTile, U32 cNumTile, U32 cNumMB) +{ + U32 i, j; + + while((cNumMB + cNumTile - 1) / cNumTile > 65535) // too few tiles + cNumTile ++; + + for(i = cNumTile, j = cNumMB; i > 1; i --){ + pTile[cNumTile - i] = (j + i - 1) / i; + j -= pTile[cNumTile - i]; + } + + return cNumTile; +} + +U32 validateTiling(U32 * pTile, U32 cNumTile, U32 cNumMB) +{ + U32 i, cMBs; + + if(cNumTile == 0) + cNumTile = 1; + if(cNumTile > cNumMB) // too many tiles + cNumTile = 1; + if(cNumTile > MAX_TILES) + cNumTile = MAX_TILES; + + for(i = cMBs = 0; i + 1 < cNumTile; i ++){ + if(pTile[i] == 0 || pTile[i] > 65535){ // invalid tile setting, resetting to uniform tiling + cNumTile = setUniformTiling(pTile, cNumTile, cNumMB); + break; + } + + cMBs += pTile[i]; + + if(cMBs >= cNumMB){ + cNumTile = i + 1; + break; + } + } + + // last tile + if(cNumMB - cMBs > 65536) + cNumTile = setUniformTiling(pTile, cNumTile, cNumMB); + + for(i = 1; i < cNumTile; i ++) + pTile[i] += pTile[i - 1]; + for(i = cNumTile - 1; i > 0; i --) + pTile[i] = pTile[i - 1]; + pTile[0] = 0; + + return cNumTile; +} + +/************************************************************************* + Validate and adjust input params here +*************************************************************************/ +Int ValidateArgs(CWMImageInfo* pII, CWMIStrCodecParam *pSCP) +{ + int i; + Bool bTooNarrowTile = FALSE; + + if(pII->cWidth > (1 << 28) || pII->cHeight > (1 << 28) || pII->cWidth == 0 || pII->cHeight == 0){ + printf("Unsurpported image size!\n"); + return ICERR_ERROR; // unsurpported image size + } + + if (((pSCP->cfColorFormat == YUV_420) || (pSCP->cfColorFormat == YUV_422)) && (pSCP->olOverlap == OL_TWO) && ((Int)(((U32)pII->cWidth + 15) >> 4) < 2)) { + printf("Image width must be at least 2 MB wide for subsampled chroma and two levels of overlap!\n"); + return ICERR_ERROR; + } + + if(pSCP->sbSubband == SB_ISOLATED || pSCP->sbSubband >= SB_MAX) // not allowed + pSCP->sbSubband = SB_ALL; + + if(pII->bdBitDepth == BD_5 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 16 || pII->cLeadingPadding != 0)){ + printf("Unsupported BD_5 image format!\n"); + return ICERR_ERROR; // BD_5 must be compact RGB! + } + if(pII->bdBitDepth == BD_565 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 16 || pII->cLeadingPadding != 0)){ + printf("Unsupported BD_565 image format!\n"); + return ICERR_ERROR; // BD_5 must be compact RGB! + } + if(pII->bdBitDepth == BD_10 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 32 || pII->cLeadingPadding != 0)){ + printf("Unsupported BD_10 image format!\n"); + return ICERR_ERROR; // BD_10 must be compact RGB! + } + + if((pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_565 || pII->bdBitDepth == BD_10) && + (pSCP->cfColorFormat != YUV_420 && pSCP->cfColorFormat != YUV_422 && pSCP->cfColorFormat != Y_ONLY)) + pSCP->cfColorFormat = YUV_444; + + if(BD_1 == pII->bdBitDepth){ // binary image + if(pII->cfColorFormat != Y_ONLY){ + printf("BD_1 image must be black-and white!\n"); + return ICERR_ERROR; + } + pSCP->cfColorFormat = Y_ONLY; // can only be black white + } + + if(pSCP->bdBitDepth != BD_LONG) + pSCP->bdBitDepth = BD_LONG; // currently only support 32 bit internally + + if(pSCP->uAlphaMode > 1 && (pII->cfColorFormat == YUV_420 || pII->cfColorFormat == YUV_422 + || pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_10 + || pII->bdBitDepth == BD_1)) + { + printf("Alpha is not supported for this pixel format!\n"); + return ICERR_ERROR; + } + + if((pSCP->cfColorFormat == YUV_420 || pSCP->cfColorFormat == YUV_422) && (pII->bdBitDepth == BD_16F || pII->bdBitDepth == BD_32F || pII->cfColorFormat == CF_RGBE)) + { + printf("Float or RGBE images must be encoded with YUV 444!\n"); + return ICERR_ERROR; + } + + // adjust tiling + pSCP->cNumOfSliceMinus1V = validateTiling(pSCP->uiTileX, pSCP->cNumOfSliceMinus1V + 1, (((U32)pII->cWidth + 15) >> 4)) - 1; + pSCP->cNumOfSliceMinus1H = validateTiling(pSCP->uiTileY, pSCP->cNumOfSliceMinus1H + 1, (((U32)pII->cHeight + 15) >> 4)) - 1; + + if (pSCP->bUseHardTileBoundaries && ((pSCP->cfColorFormat == YUV_420) || (pSCP->cfColorFormat == YUV_422)) && (pSCP->olOverlap == OL_TWO)) { + for (i = 1; i < (int) (pSCP->cNumOfSliceMinus1H + 1); i++) { + if ((Int)(pSCP->uiTileY[i] - pSCP->uiTileY[i - 1]) < 2) { + bTooNarrowTile = TRUE; + break; + } + } + if ((Int)((((U32)pII->cWidth + 15) >> 4) - pSCP->uiTileY[pSCP->cNumOfSliceMinus1H]) < 2) + bTooNarrowTile = TRUE; + } + if (bTooNarrowTile) { + printf("Tile width must be at least 2 MB wide for hard tiles, subsampled chroma, and two levels of overlap!\n"); + return ICERR_ERROR; + } + + if(pSCP->cChannel > MAX_CHANNELS) + return ICERR_ERROR; + + /** supported color transcoding **/ + /** ARGB, RGB => YUV_444, YUV_422, YUV_420, Y_ONLY **/ + /** YUV_444 => YUV_422, YUV_420, Y_ONLY **/ + /** YUV_422 => YUV_420, Y_ONLY **/ + /** YUV_420 => Y_ONLY **/ + + /** unsupported color transcoding **/ + /** Y_ONLY, YUV_420, YUV_422 => YUV_444 **/ + /** Y_ONLY, YUV_420 => YUV_422 **/ + /** Y_ONLY => YUV_420 **/ + if((pII->cfColorFormat == Y_ONLY && pSCP->cfColorFormat != Y_ONLY) || + (pSCP->cfColorFormat == YUV_422 && (pII->cfColorFormat == YUV_420 || pII->cfColorFormat == Y_ONLY)) || + (pSCP->cfColorFormat == YUV_444 && (pII->cfColorFormat == YUV_422 || pII->cfColorFormat == YUV_420 || pII->cfColorFormat == Y_ONLY))){ + pSCP->cfColorFormat = pII->cfColorFormat; // force not to do color transcoding! + } + else if (pII->cfColorFormat == NCOMPONENT) { + pSCP->cfColorFormat = NCOMPONENT; // force not to do color transcoding! + } + if (CMYK == pII->cfColorFormat && pSCP->cfColorFormat == NCOMPONENT) + { + pSCP->cfColorFormat = CMYK; + } + + if(pSCP->cfColorFormat != NCOMPONENT){ + if(pSCP->cfColorFormat == Y_ONLY) + pSCP->cChannel = 1; + else if(pSCP->cfColorFormat == CMYK) + pSCP->cChannel = 4; + else + pSCP->cChannel = 3; + } + + if(pSCP->sbSubband >= SB_MAX) + pSCP->sbSubband = SB_ALL; + + + pII->cChromaCenteringX = 0; + pII->cChromaCenteringY = 0; + + return ICERR_OK; +} + +/************************************************************************* + Initialization of CWMImageStrCodec struct +*************************************************************************/ +static Void InitializeStrEnc(CWMImageStrCodec *pSC, + const CWMImageInfo* pII, const CWMIStrCodecParam *pSCP) +{ + pSC->cbStruct = sizeof(*pSC); + pSC->WMII = *pII; + pSC->WMISCP = *pSCP; + + // set nExpBias + if (pSC->WMISCP.nExpBias == 0) + pSC->WMISCP.nExpBias = 4 + 128;//default + pSC->WMISCP.nExpBias += 128; // rollover arithmetic + + pSC->cRow = 0; + pSC->cColumn = 0; + + pSC->cmbWidth = (pSC->WMII.cWidth + 15) / 16; + pSC->cmbHeight = (pSC->WMII.cHeight + 15) / 16; + + pSC->Load = inputMBRow; + pSC->Quantize = quantizeMacroblock; + pSC->ProcessTopLeft = processMacroblock; + pSC->ProcessTop = processMacroblock; + pSC->ProcessTopRight = processMacroblock; + pSC->ProcessLeft = processMacroblock; + pSC->ProcessCenter = processMacroblock; + pSC->ProcessRight = processMacroblock; + pSC->ProcessBottomLeft = processMacroblock; + pSC->ProcessBottom = processMacroblock; + pSC->ProcessBottomRight = processMacroblock; + + pSC->m_pNextSC = NULL; + pSC->m_bSecondary = FALSE; +} + +/************************************************************************* + Streaming API init +*************************************************************************/ +Int ImageStrEncInit( + CWMImageInfo* pII, + CWMIStrCodecParam *pSCP, + CTXSTRCODEC* pctxSC) +{ + static size_t cbChannels[BD_MAX] = {2, 4}; + + size_t cbChannel = 0, cblkChroma = 0, i; + size_t cbMacBlockStride = 0, cbMacBlockChroma = 0, cMacBlock = 0; + + CWMImageStrCodec* pSC = NULL, *pNextSC = NULL; + char* pb = NULL; + size_t cb = 0; + Bool b32bit = sizeof(size_t) == 4; + + Int err; + + if(ValidateArgs(pII, pSCP) != ICERR_OK){ + goto ErrorExit; + } + + //================================================ + *pctxSC = NULL; + + //================================================ + cbChannel = cbChannels[pSCP->bdBitDepth]; + cblkChroma = cblkChromas[pSCP->cfColorFormat]; + cbMacBlockStride = cbChannel * 16 * 16; + cbMacBlockChroma = cbChannel * 16 * cblkChroma; + cMacBlock = (pII->cWidth + 15) / 16; + + //================================================ + cb = sizeof(*pSC) + (128 - 1) + (PACKETLENGTH * 4 - 1) + (PACKETLENGTH * 2 ) + sizeof(*pSC->pIOHeader); + i = cbMacBlockStride + cbMacBlockChroma * (pSCP->cChannel - 1); + if(b32bit) // integer overlow/underflow check for 32-bit system + if(((cMacBlock >> 15) * i) & 0xffff0000) + return ICERR_ERROR; + i *= cMacBlock * 2; + cb += i; + + pb = malloc(cb); + if (NULL == pb) + { + goto ErrorExit; + } + memset(pb, 0, cb); + + //================================================ + pSC = (CWMImageStrCodec*)pb; pb += sizeof(*pSC); + + // Set up perf timers + PERFTIMER_ONLY(pSC->m_fMeasurePerf = pSCP->fMeasurePerf); + PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEndToEndPerf); + PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEncDecPerf); + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf); + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + PERFTIMER_COPYSTARTTIME(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf, pSC->m_ptEndToEndPerf); + + pSC->m_param.cfColorFormat = pSCP->cfColorFormat; + pSC->m_param.bAlphaChannel = (pSCP->uAlphaMode == 3); + pSC->m_param.cNumChannels = pSCP->cChannel; + pSC->m_param.cExtraPixelsTop = pSC->m_param.cExtraPixelsBottom + = pSC->m_param.cExtraPixelsLeft = pSC->m_param.cExtraPixelsRight = 0; + + pSC->cbChannel = cbChannel; + + pSC->m_param.bTranscode = pSC->bTileExtraction = FALSE; + + //================================================ + InitializeStrEnc(pSC, pII, pSCP); + + //================================================ + // 2 Macro Row buffers for each channel + pb = ALIGNUP(pb, 128); + for (i = 0; i < pSC->m_param.cNumChannels; i++) { + pSC->a0MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth; + pSC->a1MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth; + cbMacBlockStride = cbMacBlockChroma; + } + + //================================================ + // lay 2 aligned IO buffers just below pIO struct + pb = (char*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2; + pSC->pIOHeader = (BitIOInfo*)pb; + + //================================================ + err = StrEncInit(pSC); + if (ICERR_OK != err) + goto ErrorExit; + + // if interleaved alpha is needed + if (pSC->m_param.bAlphaChannel) { + cbMacBlockStride = cbChannel * 16 * 16; + // 1. allocate new pNextSC info + //================================================ + cb = sizeof(*pNextSC) + (128 - 1) + cbMacBlockStride * cMacBlock * 2; + pb = malloc(cb); + if (NULL == pb) + { + goto ErrorExit; + } + memset(pb, 0, cb); + //================================================ + pNextSC = (CWMImageStrCodec*)pb; pb += sizeof(*pNextSC); + + // 2. initialize pNextSC + pNextSC->m_param.cfColorFormat = Y_ONLY; + pNextSC->m_param.cNumChannels = 1; + pNextSC->m_param.bAlphaChannel = TRUE; + pNextSC->cbChannel = cbChannel; + //================================================ + + // 3. initialize arrays + InitializeStrEnc(pNextSC, pII, pSCP); + //================================================ + + // 2 Macro Row buffers for each channel + pb = ALIGNUP(pb, 128); + pNextSC->a0MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth; + pNextSC->a1MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth; + //================================================ + pNextSC->pIOHeader = pSC->pIOHeader; + //================================================ + + // 4. link pSC->pNextSC = pNextSC + pNextSC->m_pNextSC = pSC; + pNextSC->m_bSecondary = TRUE; + + // 5. StrEncInit + StrEncInit(pNextSC); + + // 6. Write header of image plane + WriteImagePlaneHeader(pNextSC); + } + + pSC->m_pNextSC = pNextSC; + //================================================ + *pctxSC = (CTXSTRCODEC)pSC; + + writeIndexTableNull(pSC); +#if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_ENC) || defined(WMP_OPT_TRFM_ENC) + StrEncOpt(pSC); +#endif // OPT defined + + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + return ICERR_OK; + +ErrorExit: + return ICERR_ERROR; +} + +/************************************************************************* + Streaming API encode +*************************************************************************/ +Int ImageStrEncEncode( + CTXSTRCODEC ctxSC, + const CWMImageBufferInfo* pBI) +{ + CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC; + CWMImageStrCodec* pNextSC = pSC->m_pNextSC; + ImageDataProc ProcessLeft, ProcessCenter, ProcessRight; + + if (sizeof(*pSC) != pSC->cbStruct) + { + return ICERR_ERROR; + } + + //================================ + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + + pSC->WMIBI = *pBI; + pSC->cColumn = 0; + initMRPtr(pSC); + if (pNextSC) + pNextSC->WMIBI = *pBI; + + if (0 == pSC->cRow) { + ProcessLeft = pSC->ProcessTopLeft; + ProcessCenter = pSC->ProcessTop; + ProcessRight = pSC->ProcessTopRight; + } + else { + ProcessLeft = pSC->ProcessLeft; + ProcessCenter = pSC->ProcessCenter; + ProcessRight = pSC->ProcessRight; + } + + if( pSC->Load(pSC) != ICERR_OK ) + return ICERR_ERROR; + if(ProcessLeft(pSC) != ICERR_OK) + return ICERR_ERROR; + advanceMRPtr(pSC); + + //================================ + for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn) { + if(ProcessCenter(pSC) != ICERR_OK) + return ICERR_ERROR; + advanceMRPtr(pSC); + } + + //================================ + if(ProcessRight(pSC) != ICERR_OK) + return ICERR_ERROR; + if (pSC->cRow) + advanceOneMBRow(pSC); + + ++pSC->cRow; + swapMRPtr(pSC); + + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + return ICERR_OK; +} + +/************************************************************************* + Streaming API term +*************************************************************************/ +Int ImageStrEncTerm( + CTXSTRCODEC ctxSC) +{ + CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC; + // CWMImageStrCodec *pNextSC = pSC->m_pNextSC; + + if (sizeof(*pSC) != pSC->cbStruct) + { + return ICERR_ERROR; + } + + //================================ + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + pSC->cColumn = 0; + initMRPtr(pSC); + + pSC->ProcessBottomLeft(pSC); + advanceMRPtr(pSC); + + //================================ + for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn) { + pSC->ProcessBottom(pSC); + advanceMRPtr(pSC); + } + + //================================ + pSC->ProcessBottomRight(pSC); + + //================================ + StrEncTerm(pSC); + + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf); + PERFTIMER_REPORT(pSC->m_fMeasurePerf, pSC); + PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf); + + free(pSC); + return ICERR_OK; +} + +// centralized UV downsampling +#define DF_ODD ((((d1 + d2 + d3) << 2) + (d2 << 1) + d0 + d4 + 8) >> 4) +Void downsampleUV(CWMImageStrCodec * pSC) +{ + const COLORFORMAT cfInt = pSC->m_param.cfColorFormat; + const COLORFORMAT cfExt = pSC->WMII.cfColorFormat; + PixelI * pSrc, * pDst; + PixelI d0, d1, d2, d3, d4; + size_t iChannel, iRow, iColumn; + + for(iChannel = 1; iChannel < 3; iChannel ++){ + if(cfExt != YUV_422){ // need to do horizontal downsampling, 444 => 422 + const size_t cShift = (cfInt == YUV_422 ? 1 : 0); + + pSrc = (iChannel == 1 ? pSC->pResU : pSC->pResV); + pDst = (cfInt == YUV_422 ? pSC->p1MBbuffer[iChannel] : pSrc); + + for(iRow = 0; iRow < 16; iRow ++){ + d0 = d4 = pSrc[idxCC[iRow][2]], d1 = d3 = pSrc[idxCC[iRow][1]], d2 = pSrc[idxCC[iRow][0]]; // left boundary + + for(iColumn = 0; iColumn + 2 < pSC->cmbWidth * 16; iColumn += 2){ + pDst[((iColumn >> 4) << (8 - cShift)) + idxCC[iRow][(iColumn & 15) >> cShift]] = DF_ODD; + d0 = d2, d1 = d3, d2 = d4; + d3 = pSrc[(((iColumn + 3) >> 4) << 8) + idxCC[iRow][(iColumn + 3) & 0xf]]; + d4 = pSrc[(((iColumn + 4) >> 4) << 8) + idxCC[iRow][(iColumn + 4) & 0xf]]; + } + + d4 = d2; // right boundary + pDst[((iColumn >> 4) << (8 - cShift)) + idxCC[iRow][(iColumn & 15) >> cShift]] = DF_ODD; + } + } + + if(cfInt == YUV_420){ // need to do vertical downsampling + const size_t cShift = (cfExt == YUV_422 ? 0 : 1); + PixelI * pBuf[4]; + size_t mbOff, pxOff; + + pDst = pSC->p1MBbuffer[iChannel]; + pSrc = (iChannel == 1 ? pSC->pResU : pSC->pResV); + pBuf[0] = pSrc + (pSC->cmbWidth << (cfExt == YUV_422 ? 7 : 8)); + pBuf[1] = pBuf[0] + pSC->cmbWidth * 8, pBuf[2] = pBuf[1] + pSC->cmbWidth * 8, pBuf[3] = pBuf[2] + pSC->cmbWidth * 8; + + for(iColumn = 0; iColumn < pSC->cmbWidth * 8; iColumn ++){ + mbOff = (iColumn >> 3) << (7 + cShift); + pxOff = (iColumn & 7) << cShift; + + if(pSC->cRow == 0) // top image boundary + d0 = d4 = pSrc[mbOff + idxCC[2][pxOff]], d1 = d3 = pSrc[mbOff + idxCC[1][pxOff]], d2 = pSrc[mbOff + idxCC[0][pxOff]]; // top MB boundary + else{ + // last row of previous MB row + d0 = pBuf[0][iColumn], d1 = pBuf[1][iColumn], d2 = pBuf[2][iColumn], d3 = pBuf[3][iColumn], d4 = pSrc[mbOff + idxCC[0][pxOff]]; + pSC->p0MBbuffer[iChannel][((iColumn >> 3) << 6) + idxCC_420[7][iColumn & 7]] = DF_ODD; + + // for first row of current MB + d0 = pBuf[2][iColumn], d1 = pBuf[3][iColumn]; + d2 = pSrc[mbOff + idxCC[0][pxOff]], d3 = pSrc[mbOff + idxCC[1][pxOff]], d4 = pSrc[mbOff + idxCC[2][pxOff]]; + } + + for(iRow = 0; iRow < 12; iRow += 2){ + pDst[((iColumn >> 3) << 6) + idxCC_420[iRow >> 1][iColumn & 7]] = DF_ODD; + d0 = d2, d1 = d3, d2 = d4; + d3 = pSrc[mbOff + idxCC[iRow + 3][pxOff]]; + d4 = pSrc[mbOff + idxCC[iRow + 4][pxOff]]; + } + + //last row of current MB + pDst[((iColumn >> 3) << 6) + idxCC_420[6][iColumn & 7]] = DF_ODD; + d0 = d2, d1 = d3, d2 = d4; + d3 = pSrc[mbOff + idxCC[iRow + 3][pxOff]]; + + if(pSC->cRow + 1 == pSC->cmbHeight){ // bottom image boundary + d4 = d2; + pDst[((iColumn >> 3) << 6) + idxCC_420[7][iColumn & 7]] = DF_ODD; + } + else{ + for(iRow = 0; iRow < 4; iRow ++) + pBuf[iRow][iColumn] = pSrc[mbOff + idxCC[iRow + 12][pxOff]]; + } + } + } + } +} + +// centralized horizontal padding +Void padHorizontally(CWMImageStrCodec * pSC) +{ + if(pSC->WMII.cWidth != pSC->cmbWidth * 16){ // horizontal padding is necessary! + const COLORFORMAT cfExt = pSC->WMISCP.bYUVData ? + pSC->m_param.cfColorFormat : pSC->WMII.cfColorFormat; + size_t cFullChannel = pSC->WMISCP.cChannel; + size_t iLast = pSC->WMII.cWidth - 1; + PixelI * pCh[16]; + size_t iChannel, iColumn, iRow; + + if(cfExt == YUV_420 || cfExt == YUV_422 || cfExt == Y_ONLY) + cFullChannel = 1; + + assert(cFullChannel <= 16); + + assert(pSC->WMISCP.cChannel <= 16); + for(iChannel = 0; iChannel < pSC->WMISCP.cChannel; iChannel ++) + pCh[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15]; + + if(pSC->m_bUVResolutionChange) + pCh[1] = pSC->pResU, pCh[2] = pSC->pResV; + + // pad full resoluton channels + for(iRow = 0; iRow < 16; iRow ++){ + const size_t iPosLast = ((iLast >> 4) << 8) + idxCC[iRow][iLast & 0xf]; + for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 16; iColumn ++){ + const size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cFullChannel; iChannel ++) + pCh[iChannel & 15][iPos] = pCh[iChannel & 15][iPosLast]; + } + } + + if(cfExt == YUV_422) // pad YUV_422 UV + for(iLast >>= 1, iRow = 0; iRow < 16; iRow ++){ + const size_t iPosLast = ((iLast >> 3) << 7) + idxCC[iRow][iLast & 7]; + for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 8; iColumn ++){ + const size_t iPos = ((iColumn >> 3) << 7) + idxCC[iRow][iColumn & 7]; + for(iChannel = 1; iChannel < 3; iChannel ++) + pCh[iChannel][iPos] = pCh[iChannel][iPosLast]; + } + } + else if(cfExt == YUV_420) // pad YUV_420 UV + for(iLast >>= 1, iRow = 0; iRow < 8; iRow ++){ + const size_t iPosLast = ((iLast >> 3) << 6) + idxCC_420[iRow][iLast & 7]; + for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 8; iColumn ++){ + const size_t iPos = ((iColumn >> 3) << 6) + idxCC_420[iRow][iColumn & 7]; + for(iChannel = 1; iChannel < 3; iChannel ++) + pCh[iChannel][iPos] = pCh[iChannel][iPosLast]; + } + } + } +} + +// centralized alpha channel color conversion, small perf penalty +Int inputMBRowAlpha(CWMImageStrCodec* pSC) +{ + if(pSC->m_bSecondary == FALSE && pSC->m_pNextSC != NULL){ // alpha channel is present + const size_t cShift = (pSC->m_pNextSC->m_param.bScaledArith ? (SHIFTZERO + QPFRACBITS) : 0); + const BITDEPTH_BITS bdExt = pSC->WMII.bdBitDepth; + const size_t iAlphaPos = pSC->WMII.cLeadingPadding + (pSC->WMII.cfColorFormat == CMYK ? 4 : 3);//only RGB and CMYK may have interleaved alpha + const size_t cRow = pSC->WMIBI.cLine; + const size_t cColumn = pSC->WMII.cWidth; + const U8 * pSrc0 = (U8 *)pSC->WMIBI.pv; + PixelI * pA = pSC->m_pNextSC->p1MBbuffer[0]; + size_t iRow, iColumn; + + for(iRow = 0; iRow < 16; iRow ++){ + if(bdExt == BD_8){ + const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3); + const U8 * pSrc = pSrc0; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride) + pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((PixelI)pSrc[iAlphaPos] - (1 << 7)) << cShift; + } + else if(bdExt == BD_16){ + const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(U16); + const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift; + const U16 * pSrc = (U16 *)pSrc0; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride) + pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((((PixelI)pSrc[iAlphaPos] - (1 << 15)) >> nLenMantissaOrShift) << cShift); + } + else if(bdExt == BD_16S){ + const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(I16); + const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift; + const I16 * pSrc = (I16 *)pSrc0; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride) + pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = (((PixelI)pSrc[iAlphaPos] >> nLenMantissaOrShift) << cShift); + } + else if(bdExt == BD_16F){ + const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(U16); + const I16 * pSrc = (I16 *)pSrc0; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride) + pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = forwardHalf (pSrc[iAlphaPos]) << cShift; + } + else if(bdExt == BD_32S){ + const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(I32); + const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift; + const I32 * pSrc = (I32 *)pSrc0; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride) + pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = (((PixelI)pSrc[iAlphaPos] >> nLenMantissaOrShift) << cShift); + } + else if(bdExt == BD_32F){ + const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(float); + const U8 nLen = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift; + const I8 nExpBias = pSC->m_pNextSC->WMISCP.nExpBias; + const float * pSrc = (float *)pSrc0; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride) + pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = float2pixel (pSrc[iAlphaPos], nExpBias, nLen) << cShift; + } + else // not supported + return ICERR_ERROR; + + if(iRow + 1 < cRow) // vertical padding! + pSrc0 += pSC->WMIBI.cbStride; + + for(iColumn = cColumn; iColumn < pSC->cmbWidth * 16; iColumn ++) // horizontal padding + pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = pA[(((cColumn - 1) >> 4) << 8) + idxCC[iRow][(cColumn - 1) & 0xf]]; + } + } + + return ICERR_OK; +} + +// input one MB row of image data from input buffer +Int inputMBRow(CWMImageStrCodec* pSC) +{ + const size_t cShift = (pSC->m_param.bScaledArith ? (SHIFTZERO + QPFRACBITS) : 0); + const BITDEPTH_BITS bdExt = pSC->WMII.bdBitDepth; + COLORFORMAT cfExt = pSC->WMII.cfColorFormat; + const COLORFORMAT cfInt = pSC->m_param.cfColorFormat; + const size_t cPixelStride = (pSC->WMII.cBitsPerUnit >> 3); + const size_t iRowStride = + (cfExt == YUV_420 || (pSC->WMISCP.bYUVData && pSC->m_param.cfColorFormat==YUV_420)) ? 2 : 1; + const size_t cRow = pSC->WMIBI.cLine; + const size_t cColumn = pSC->WMII.cWidth; + const size_t iB = (pSC->WMII.bRGB ? 2 : 0); + const size_t iR = 2 - iB; + const U8 * pSrc0 = (U8 *)pSC->WMIBI.pv; + const U8 nLen = pSC->WMISCP.nLenMantissaOrShift; + const I8 nExpBias = pSC->WMISCP.nExpBias; + + PixelI *pY = pSC->p1MBbuffer[0], *pU = pSC->p1MBbuffer[1], *pV = pSC->p1MBbuffer[2]; + size_t iRow, iColumn, iPos; + + // guard input buffer + if(checkImageBuffer(pSC, cColumn, cRow) != ICERR_OK) + return ICERR_ERROR; + + if(pSC->m_bUVResolutionChange) // will do downsampling somewhere else! + pU = pSC->pResU, pV = pSC->pResV; + else if(cfInt == Y_ONLY) // xxx to Y_ONLY transcoding! + pU = pV = pY; // write pY AFTER pU and pV so Y will overwrite U&V + + for(iRow = 0; iRow < 16; iRow += iRowStride){ + if (pSC->WMISCP.bYUVData){ + I32 * pSrc = (I32 *)pSrc0 + pSC->WMII.cLeadingPadding; + + switch(pSC->m_param.cfColorFormat){ + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + const size_t cChannel = pSC->m_param.cNumChannels; + PixelI * pChannel[16]; + size_t iChannel; + + assert(cChannel <= 16); + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pChannel[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15]; + if(pSC->m_bUVResolutionChange) + pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cChannel){ + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pChannel[iChannel & 15][iPos] = (PixelI)pSrc[iChannel & 15]; + } + } + break; + + case YUV_422: + for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += 4){ + if(cfInt != Y_ONLY){ + iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7]; + pU[iPos] = (PixelI)pSrc[0]; + pV[iPos] = (PixelI)pSrc[2]; + } + + pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (PixelI)pSrc[1]; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (PixelI)pSrc[3]; + } + break; + + case YUV_420: + for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += 6){ + if(cfInt != Y_ONLY){ + iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7]; + pU[iPos] = (PixelI)pSrc[4]; + pV[iPos] = (PixelI)pSrc[5]; + } + + pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (PixelI)pSrc[0]; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (PixelI)pSrc[1]; + pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (PixelI)pSrc[2]; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (PixelI)pSrc[3]; + } + break; + + default: + assert(0); + break; + } + } + else if(bdExt == BD_8){ + const U8 * pSrc = pSrc0 + pSC->WMII.cLeadingPadding; + const PixelI iOffset = (128 << cShift); + + switch(cfExt){ + case CF_RGB: + assert (pSC->m_bSecondary == FALSE); + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){ + PixelI r = ((PixelI)pSrc[iR]) << cShift, g = ((PixelI)pSrc[1]) << cShift, b = ((PixelI)pSrc[iB]) << cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset; + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + const size_t cChannel = pSC->m_param.cNumChannels; + PixelI * pChannel[16]; + size_t iChannel; + + assert(cChannel <= 16); + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pChannel[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15]; + if(pSC->m_bUVResolutionChange) + pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){ + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pChannel[iChannel & 15][iPos] = (((PixelI)pSrc[iChannel & 15]) << cShift) - iOffset; + } + break; + } + + case CF_RGBE: + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){ + PixelI iExp = (PixelI)pSrc[3]; + PixelI r = forwardRGBE (pSrc[0], iExp) << cShift; + PixelI g = forwardRGBE (pSrc[1], iExp) << cShift; + PixelI b = forwardRGBE (pSrc[2], iExp) << cShift; + + _CC(r, g, b); + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g; + } + break; + + case CMYK: + { + PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding! + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){ + PixelI c = ((PixelI)pSrc[0]) << cShift; + PixelI m = ((PixelI)pSrc[1]) << cShift; + PixelI y = ((PixelI)pSrc[2]) << cShift; + PixelI k = ((PixelI)pSrc[3]) << cShift; + + _CC_CMYK(c, m, y, k); + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = iOffset - m; + } + break; + } + + case YUV_422: + for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cPixelStride){ + if(cfInt != Y_ONLY){ + iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7]; + pU[iPos] = (((PixelI)pSrc[0]) << cShift) - iOffset; + pV[iPos] = (((PixelI)pSrc[2]) << cShift) - iOffset; + } + + pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset; + } + break; + + case YUV_420: + for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cPixelStride){ + if(cfInt != Y_ONLY){ + iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7]; + pU[iPos] = (((PixelI)pSrc[4]) << cShift) - iOffset; + pV[iPos] = (((PixelI)pSrc[5]) << cShift) - iOffset; + } + + pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[0]) << cShift) - iOffset; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset; + pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (((PixelI)pSrc[2]) << cShift) - iOffset; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset; + } + break; + + default: + assert(0); + break; + } + } + else if(bdExt == BD_16){ + const U16 * pSrc = (U16 *)pSrc0 + pSC->WMII.cLeadingPadding; + const size_t cStride = cPixelStride / sizeof(U16); + const PixelI iOffset = ((1 << 15) >> nLen) << cShift; + + switch(cfExt){ + case CF_RGB: + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + PixelI r = ((PixelI)pSrc[0] >> nLen) << cShift, g = ((PixelI)pSrc[1] >> nLen) << cShift, b = ((PixelI)pSrc[2] >> nLen) << cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset; + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + const size_t cChannel = pSC->WMISCP.cChannel; + size_t iChannel; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pSC->p1MBbuffer[iChannel][iPos] = (((PixelI)pSrc[iChannel] >> nLen) << cShift) - iOffset; + } + break; + } + + case CMYK: + { + PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding! + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + PixelI c = ((PixelI)pSrc[0] >> nLen) << cShift; + PixelI m = ((PixelI)pSrc[1] >> nLen) << cShift; + PixelI y = ((PixelI)pSrc[2] >> nLen) << cShift; + PixelI k = ((PixelI)pSrc[3] >> nLen) << cShift; + + _CC_CMYK(c, m, y, k); + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = iOffset - m; + } + break; + } + + case YUV_422: + for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cStride){ + if(cfInt != Y_ONLY){ + iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7]; + pU[iPos] = (((PixelI)pSrc[0]) << cShift) - iOffset; + pV[iPos] = (((PixelI)pSrc[2]) << cShift) - iOffset; + } + + pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset; + } + break; + + case YUV_420: + for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cStride){ + if(cfInt != Y_ONLY){ + iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7]; + pU[iPos] = (((PixelI)pSrc[4]) << cShift) - iOffset; + pV[iPos] = (((PixelI)pSrc[5]) << cShift) - iOffset; + } + + pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[0]) << cShift) - iOffset; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset; + pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (((PixelI)pSrc[2]) << cShift) - iOffset; + pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset; + } + break; + + default: + assert(0); + break; + } + } + else if(bdExt == BD_16S){ + const I16 * pSrc = (I16 *)pSrc0 + pSC->WMII.cLeadingPadding; + const size_t cStride = cPixelStride / sizeof(I16); + + switch(cfExt){ + case CF_RGB: + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + PixelI r = ((PixelI)pSrc[0] >> nLen) << cShift, g = ((PixelI)pSrc[1] >> nLen) << cShift, b = ((PixelI)pSrc[2] >> nLen) << cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g; + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + const size_t cChannel = pSC->WMISCP.cChannel; + size_t iChannel; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pSC->p1MBbuffer[iChannel][iPos] = (((PixelI)pSrc[iChannel] >> nLen) << cShift); + } + } + break; + + case CMYK: + { + PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding! + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + PixelI c = ((PixelI)pSrc[0] >> nLen) << cShift; + PixelI m = ((PixelI)pSrc[1] >> nLen) << cShift; + PixelI y = ((PixelI)pSrc[2] >> nLen) << cShift; + PixelI k = ((PixelI)pSrc[3] >> nLen) << cShift; + + _CC_CMYK(c, m, y, k); + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = -m; + } + } + break; + + default: + assert(0); + break; + } + } + else if(bdExt == BD_16F){ + const I16 * pSrc = (I16 *)pSrc0 + pSC->WMII.cLeadingPadding; + const size_t cStride = cPixelStride / sizeof(U16); + + switch(cfExt){ + case CF_RGB: + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + PixelI r = forwardHalf (pSrc[0]) << cShift; + PixelI g = forwardHalf (pSrc[1]) << cShift; + PixelI b = forwardHalf (pSrc[2]) << cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g; + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + const size_t cChannel = pSC->WMISCP.cChannel; // check xxx => Y_ONLY transcoding! + size_t iChannel; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pSC->p1MBbuffer[iChannel][iPos] = forwardHalf (pSrc[iChannel]) << cShift; + } + } + break; + + default: + assert(0); + break; + } + } + else if(bdExt == BD_32){ + const U32 * pSrc = (U32 *)pSrc0 + pSC->WMII.cLeadingPadding; + const size_t cStride = cPixelStride / sizeof(U32); + const PixelI iOffset = ((1 << 31) >> nLen) << cShift; + + switch(cfExt){ + case CF_RGB: + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + PixelI r = (pSrc[0] >> nLen) << cShift, g = (pSrc[1] >> nLen) << cShift, b = (pSrc[2] >> nLen) << cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset; + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + const size_t cChannel = pSC->WMISCP.cChannel; + size_t iChannel; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pSC->p1MBbuffer[iChannel][iPos] = (pSrc[iChannel] >> nLen) << cShift; + } + break; + } + + default: + assert(0); + break; + } + } + else if(bdExt == BD_32S){ + const I32 * pSrc = (I32 *)pSrc0 + pSC->WMII.cLeadingPadding; + const size_t cStride = cPixelStride / sizeof(I32); + + switch(cfExt){ + case CF_RGB: + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + PixelI r = (pSrc[0] >> nLen)<< cShift, g = (pSrc[1] >> nLen)<< cShift, b = (pSrc[2] >> nLen)<< cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g; + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + const size_t cChannel = pSC->WMISCP.cChannel; // check xxx => Y_ONLY transcoding! + size_t iChannel; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pSC->p1MBbuffer[iChannel][iPos] = (pSrc[iChannel] >> nLen) << cShift; + } + } + break; + + default: + assert(0); + break; + } + } + else if(bdExt == BD_32F){ + const float * pSrc = (float *)pSrc0 + pSC->WMII.cLeadingPadding; + const size_t cStride = cPixelStride / sizeof(float); + + switch(cfExt){ + case CF_RGB: + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + PixelI r = float2pixel (pSrc[0], nExpBias, nLen) << cShift; + PixelI g = float2pixel (pSrc[1], nExpBias, nLen) << cShift; + PixelI b = float2pixel (pSrc[2], nExpBias, nLen) << cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g; + } + break; + + case Y_ONLY: + case YUV_444: + case NCOMPONENT: + { + const size_t cChannel = pSC->WMISCP.cChannel; + size_t iChannel; + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){ + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + for(iChannel = 0; iChannel < cChannel; iChannel ++) + pSC->p1MBbuffer[iChannel][iPos] = float2pixel (pSrc[iChannel], nExpBias, nLen) << cShift; + } + } + break; + default: + assert(0); + break; + } + } + else if(bdExt == BD_5){ // RGB 555, work for both big endian and small endian! + const U8 * pSrc = pSrc0; + const PixelI iOffset = (16 << cShift); + + assert(cfExt == CF_RGB); + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){ + PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = ((g >> 2) & 0x1F) << cShift; + + g = ((r >> 5) + ((g & 3) << 3)) << cShift, r = (r & 0x1F) << cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset; + } + } + else if(bdExt == BD_565){ // RGB 555, work for both big endian and small endian! + const U8 * pSrc = pSrc0; + const PixelI iOffset = (32 << cShift); + + assert(cfExt == CF_RGB); + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){ + PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = (g >> 3) << (cShift + 1); + + g = ((r >> 5) + ((g & 7) << 3)) << cShift, r = (r & 0x1F) << (cShift + 1); + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset; + } + } + else if(bdExt == BD_10){ //RGB 101010, work for both big endian and small endian! + const U8 * pSrc = pSrc0; + const PixelI iOffset = (512 << cShift); + + assert(cfExt == CF_RGB); + + for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){ + PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = (PixelI)pSrc[2]; + + r = (r + ((g & 3) << 8)) << cShift, g = ((g >> 2) + ((b & 0xF) << 6)) << cShift; + b = ((b >> 4) + (((PixelI)pSrc[3] & 0x3F) << 4)) << cShift; + + _CC(r, g, b); // color conversion + + iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]; + pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset; + } + } + else if(bdExt == BD_1){ + assert(cfExt == Y_ONLY); + for(iColumn = 0; iColumn < cColumn; iColumn ++) { + pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((pSC->WMISCP.bBlackWhite + (pSrc0[iColumn >> 3] >> (7 - (iColumn & 7)))) & 1) << cShift; + } + } + + if(iRow + iRowStride < cRow) // centralized vertical padding! + pSrc0 += pSC->WMIBI.cbStride; + } + + padHorizontally(pSC); // centralized horizontal padding + + // centralized down-sampling + if(pSC->m_bUVResolutionChange) + downsampleUV(pSC); + + // centralized alpha channel handdling + if (pSC->WMISCP.uAlphaMode == 3) + if(inputMBRowAlpha(pSC) != ICERR_OK) + return ICERR_ERROR; + + return ICERR_OK; +} + + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strenc_x86.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strenc_x86.c new file mode 100644 index 0000000..3e9aef0 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/encode/strenc_x86.c @@ -0,0 +1,409 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include "strcodec.h" + +#if defined(WMP_OPT_SSE2) +#include +#include + +//================================ +__m128i g_const_d1; +__m128i g_const_d0x400; +__m128i g_const_d0x7f8; + +//================================ +#if defined(WMP_OPT_CC_ENC) +__declspec(naked) void __stdcall RGB24_6( + const U8* pbRGB, + size_t cbRGB, + U8* pbYCoCg, + size_t cbYCoCg, + size_t cmb) +{ + UNREFERENCED_PARAMETER( pbRGB ); + UNREFERENCED_PARAMETER( cbRGB ); + UNREFERENCED_PARAMETER( pbYCoCg ); + UNREFERENCED_PARAMETER( cbYCoCg ); + UNREFERENCED_PARAMETER( cmb ); + __asm { + push ebp + push ebx + push esi + push edi + + mov ebp, [esp + 36] // $ebp = cmb + mov edx, [esp + 20] // $edx = pbRGB + lea ebp, [ebp + ebp * 2] // $ebp = cmb * 3 + mov ecx, [esp + 24] // $ecx = cbRGB + shl ebp, 4 // $ebp = cmb * 3 * 16 + mov edi, [esp + 28] // $edi = pbYCoCg + add edx, ebp // $edx = pbRGB + 3 * 16 * cmb + mov ebx, [esp + 32] // $ebx = cbYCoCg + neg ebp + + mov eax, esp + and esp, 0xffffff80 + sub esp, 64 + 4 * 6 + + mov [esp], ecx // cbRGB + mov [esp + 4], edx // pbRGB + 3 * 16 * cmb + mov [esp + 8], edi // pbYCoCg + mov dword ptr [esp + 12], 4 // cLoop0 = 4 + mov [esp + 16], ebp // -3 * 16 * cmb + mov [esp + 20], eax // original $esp + movdqa xmm3, [g_const_d1] + } +Loop0: + __asm mov edi, [esp + 8] // $edi = pbYCoCg + __asm mov ebp, [esp + 16] // $ebp = -3 * 16 * cmb + +Loop1: + __asm { + mov esi, [esp + 4] // $esi = pbRGB + 3 * 16 * cmb + + //================ + // scanline 0 + mov eax, [esi + ebp] + mov edx, [esi + ebp + 4] + mov ecx, [esi + ebp + 8] + add esi, [esp] // $esi += cbRGB + + mov [esp + 24], eax + shrd eax, edx, 24 + shrd edx, ecx, 16 + shr ecx, 8 + mov [esp + 24 + 4], eax + mov [esp + 24 + 20], edx + mov [esp + 24 + 16], ecx + + // scanline 1 + mov eax, [esi + ebp] + mov edx, [esi + ebp + 4] + mov ecx, [esi + ebp + 8] + add esi, [esp] + + mov [esp + 24 + 8], eax + shrd eax, edx, 24 + shrd edx, ecx, 16 + shr ecx, 8 + mov [esp + 24 + 12], eax + mov [esp + 24 + 28], edx + mov [esp + 24 + 24], ecx + + // scanline 2 + mov eax, [esi + ebp] + mov edx, [esi + ebp + 4] + mov ecx, [esi + ebp + 8] + add esi, [esp] + + mov [esp + 24 + 40], eax + shrd eax, edx, 24 + shrd edx, ecx, 16 + shr ecx, 8 + mov [esp + 24 + 44], eax + mov [esp + 24 + 60], edx + mov [esp + 24 + 56], ecx + + // scanline 3 + mov eax, [esi + ebp] + mov edx, [esi + ebp + 4] + mov ecx, [esi + ebp + 8] + add esi, [esp] + + mov [esp + 24 + 32], eax + shrd eax, edx, 24 + shrd edx, ecx, 16 + shr ecx, 8 + mov [esp + 24 + 36], eax + mov [esp + 24 + 52], edx + mov [esp + 24 + 48], ecx + + //================ + // CC 0,1 + movdqa xmm0, [esp + 24] + movdqa xmm4, [esp + 24 + 16] + movdqa xmm7, [g_const_d0x7f8] + movdqa xmm1, xmm0 + movdqa xmm5, xmm4 + movdqa xmm2, xmm0 + movdqa xmm6, xmm4 + + pslld xmm0, 3 + pslld xmm4, 3 + psrad xmm5, 5 + psrad xmm1, 5 + psrad xmm2, 13 + psrad xmm6, 13 + pand xmm0, xmm7 // R + pand xmm4, xmm7 + pand xmm1, xmm7 // G + pand xmm5, xmm7 + pand xmm2, xmm7 // B + pand xmm6, xmm7 + + psubd xmm2, xmm0 // b -= r + psubd xmm6, xmm4 + movntdq [edi + ebx * 2], xmm2 + movntdq [edi + ebx * 2 + 16], xmm6 + + paddd xmm2, xmm3 // r += ((b + 1) >> 1) - g + paddd xmm6, xmm3 + psubd xmm0, xmm1 + psubd xmm4, xmm5 + psrad xmm2, 1 + psrad xmm6, 1 + paddd xmm0, xmm2 + paddd xmm4, xmm6 + + movdqa xmm2, xmm0 // g += r >> 1 + movdqa xmm6, xmm4 + movdqa xmm7, [g_const_d0x400] + psrad xmm2, 1 + psrad xmm6, 1 + paddd xmm1, xmm2 + paddd xmm5, xmm6 + + pxor xmm2, xmm2 + pxor xmm6, xmm6 + psubd xmm1, xmm7 // g -= offset + psubd xmm5, xmm7 + psubd xmm2, xmm0 // r = -r + psubd xmm6, xmm4 + + movntdq [edi], xmm1 + movntdq [edi + 16], xmm5 + movntdq [edi + ebx], xmm2 + movntdq [edi + ebx + 16], xmm6 + + //================ + // CC 2,3 + movdqa xmm4, [esp + 24 + 48] + movdqa xmm0, [esp + 24 + 32] + movdqa xmm7, [g_const_d0x7f8] + movdqa xmm1, xmm0 + movdqa xmm5, xmm4 + movdqa xmm2, xmm0 + movdqa xmm6, xmm4 + + pslld xmm0, 3 + pslld xmm4, 3 + psrad xmm1, 5 + psrad xmm5, 5 + psrad xmm2, 13 + psrad xmm6, 13 + pand xmm0, xmm7 // R + pand xmm4, xmm7 + pand xmm1, xmm7 // G + pand xmm5, xmm7 + pand xmm2, xmm7 // B + pand xmm6, xmm7 + + psubd xmm2, xmm0 // b -= r + psubd xmm6, xmm4 + movntdq [edi + ebx * 2 + 32], xmm2 + movntdq [edi + ebx * 2 + 48], xmm6 + + paddd xmm2, xmm3 // r += ((b + 1) >> 1) - g + paddd xmm6, xmm3 + psubd xmm0, xmm1 + psubd xmm4, xmm5 + psrad xmm2, 1 + psrad xmm6, 1 + paddd xmm0, xmm2 + paddd xmm4, xmm6 + + movdqa xmm2, xmm0 // g += r >> 1 + movdqa xmm6, xmm4 + movdqa xmm7, [g_const_d0x400] + psrad xmm2, 1 + psrad xmm6, 1 + paddd xmm1, xmm2 + paddd xmm5, xmm6 + + pxor xmm2, xmm2 + pxor xmm6, xmm6 + psubd xmm1, xmm7 // g -= offset + psubd xmm5, xmm7 + psubd xmm2, xmm0 // r = -r + psubd xmm6, xmm4 + + movntdq [edi + 32], xmm1 + movntdq [edi + 48], xmm5 + movntdq [edi + ebx + 32], xmm2 + movntdq [edi + ebx + 48], xmm6 + + //================ + add edi, 256 // pbYCoCg += 256 + add ebp, 12 // pbRGB += 12 + jnz Loop1 + + //================ + add dword ptr [esp + 8], 64 // pbYCoCg += 64 + sub dword ptr [esp + 12], 1 // --cLoop0 + mov [esp + 4], esi // pbRGB += cbRGB * 4 + jnz Loop0 + + //================ + mov esp, [esp + 20] + pop edi + pop esi + pop ebx + pop ebp + ret 20 + } +} + +Int inputMBRow_RGB24_6(CWMImageStrCodec* pSC) +{ + const U8* const pbRGB = (U8*)pSC->WMIBI.pv; + const size_t cbRGB = pSC->WMIBI.cbStride; + + U8* const pbY = (U8*)pSC->p1MBbuffer[0]; + U8* const pbU = (U8*)pSC->p1MBbuffer[1]; + // U8* const pbV = (U8*)pSC->p1MBbuffer[2]; + + const size_t cmbColumn = (pSC->WMII.cWidth + 15) / 16; + + assert(BD_8 == pSC->WMII.bdBitDepth); + assert(CF_RGB == pSC->WMII.cfColorFormat); + assert(24 == pSC->WMII.cBitsPerUnit); + assert(pSC->WMII.bRGB); + assert(pSC->m_param.bScaledArith); + assert(pbU - pbY == pbV - pbU); + + RGB24_6(pbRGB + cbRGB * 0, cbRGB, pbY, pbU - pbY, cmbColumn); + return ICERR_OK; +} +#endif + +//================================ +#if defined(WMP_OPT_QT) +#if 0 +Int quantizeMacroblock(CWMImageStrCodec* pSC) +{ + assert(BD_8 == pSC->WMII.bdBitDepth); + assert(YUV_444 == pSC->m_param.cfColorFormat); + assert(pSC->m_param.bScaledArith); + assert(3 == pSC->m_param.cNumChannels); + assert(SB_ALL == pSC->WMISCP.sbSubband); + + CWMITile* pTile = pSC->pTile + pSC->cTileColumn; + CWMIMBInfo* pMBInfo = &pSC->MBInfo; + int iChannel, i, j; + + __m128 owQT[2]; + + + + for (iChannel = 0; iChannel < 3; iChannel ++) { + CWMIQuantizer* pQPDC = pTile->pQuantizerDC[iChannel]; + CWMIQuantizer* pQPLP = pTile->pQuantizerLP[iChannel] + pMBInfo->iQIndexLP; + CWMIQuantizer* pQPHP = pTile->pQuantizerHP[iChannel] + pMBInfo->iQIndexHP; + + __m128 owQT[4] = { + {pQPDC->f1_QP, pQPHP->f1_QP, pQPHP->f1_QP, pQPHP->f1_QP,}, + {pQPLP->f1_QP, pQPHP->f1_QP, pQPHP->f1_QP, pQPHP->f1_QP,}, + }; + + owQT[0].m128_f32[0] = pQPDC->f1_QP; + owQT[0].m128_f32[1] = pQPHP->f1_QP; + owQT[0].m128_f32[2] = pQPHP->f1_QP; + owQT[0].m128_f32[3] = pQPHP->f1_QP; + owQT[1].m128_f32[0] = pQPDC->f1_QP; + owQT[1].m128_f32[1] = pQPHP->f1_QP; + owQT[1].m128_f32[2] = pQPHP->f1_QP; + owQT[1].m128_f32[3] = pQPHP->f1_QP; + + + + + for(j = 0; j < 16; j ++){ + PixelI* pData = pSC->pPlane[iChannel] + blkOffset[j]; + + if(j == 0) // DC + pData[0] = (pQPDC->iMan == 0 ? QUANT_Mulless(pData[0], pQPDC->iOffset, pQPDC->iExp) : QUANT(pData[0], pQPDC->iOffset, pQPDC->iMan, pQPDC->iExp)); + else // LP + pData[0] = (pQPLP->iMan == 0 ? QUANT_Mulless(pData[0], pQPLP->iOffset, pQPLP->iExp) : QUANT(pData[0], pQPLP->iOffset, pQPLP->iMan, pQPLP->iExp)); + + // quantize HP + for(i = 1; i < 16; i ++) + pData[i] = (pQPHP->iMan == 0 ? QUANT_Mulless(pData[i], pQPHP->iOffset, pQPHP->iExp) : QUANT(pData[i], pQPHP->iOffset, pQPHP->iMan, pQPHP->iExp)); + } + } + + for (iChannel = 0; iChannel < 3; iChannel ++) { + I32* pDC = pSC->MBInfo.iBlockDC[iChannel]; + PixelI* pData = pSC->pPlane[iChannel]; + + for(i = 0; i < 16; i ++){ + pDC[i] = pData[dctIndex[2][i]]; + } + } + + return 0; +} +#endif +#endif +#endif + + +//================================ +void StrEncOpt(CWMImageStrCodec* pSC) +{ +#if defined(WMP_OPT_SSE2) + if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE) && + pSC->WMII.fPaddedUserBuffer && + 1) + { + CWMImageInfo* pII = &pSC->WMII; + // CWMIStrCodecParam* pSCP = &pSC->WMISCP; + + g_const_d1 = _mm_set_epi32(1, 1, 1, 1); + g_const_d0x400 = _mm_set_epi32(0x400, 0x400, 0x400, 0x400); + g_const_d0x7f8 = _mm_set_epi32(0x7f8, 0x7f8, 0x7f8, 0x7f8); + + if (BD_8 == pII->bdBitDepth && + CF_RGB == pII->cfColorFormat && + YUV_444 == pSC->m_param.cfColorFormat && + 24 == pII->cBitsPerUnit && + pII->bRGB && + pSC->m_param.bScaledArith && + pSC->p1MBbuffer[1] - pSC->p1MBbuffer[0] == pSC->p1MBbuffer[2] - pSC->p1MBbuffer[1] && + 1) + { +#if defined(WMP_OPT_CC_ENC) + pSC->Load = inputMBRow_RGB24_6; +#endif + } + + } +#else + UNREFERENCED_PARAMETER( pSC ); +#endif +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/adapthuff.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/adapthuff.c new file mode 100644 index 0000000..2fabc8c --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/adapthuff.c @@ -0,0 +1,511 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strcodec.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +// Huffman lookup tables +static const short g4HuffLookupTable[40] = { + 19,19,19,19,27,27,27,27,10,10,10,10,10,10,10,10, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0 }; + +static const short g5HuffLookupTable[2][42] = {{ + 28,28,36,36,19,19,19,19,10,10,10,10,10,10,10,10, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0 }, + { + 11,11,11,11,19,19,19,19,27,27,27,27,35,35,35,35, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0 }}; + +static const short g6HuffLookupTable[4][44] = {{ + 13,29,44,44,19,19,19,19,34,34,34,34,34,34,34,34, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0 }, + { + 12,12,28,28,43,43,43,43,2,2,2,2,2,2,2,2, + 18,18,18,18,18,18,18,18,34,34,34,34,34,34,34,34, + 0,0,0,0,0,0,0,0,0,0,0,0 }, + { + 4,4,12,12,43,43,43,43,18,18,18,18,18,18,18,18, + 26,26,26,26,26,26,26,26,34,34,34,34,34,34,34,34, + 0,0,0,0,0,0,0,0,0,0,0,0 }, + { + 5,13,36,36,43,43,43,43,18,18,18,18,18,18,18,18, + 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, + 0,0,0,0,0,0,0,0,0,0,0,0 }}; + +static const short g7HuffLookupTable[2][46] = {{ + 45,53,36,36,27,27,27,27,2,2,2,2,2,2,2,2, + 10,10,10,10,10,10,10,10,18,18,18,18,18,18,18,18, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, + { + -32736,37,28,28,19,19,19,19,10,10,10,10,10,10,10,10, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5,6,0,0,0,0,0,0,0,0,0,0,0,0 }}; + +static const short g8HuffLookupTable[2][48] = {{ + 53,21,28,28,11,11,11,11,43,43,43,43,59,59,59,59, + 2,2,2,2,2,2,2,2,34,34,34,34,34,34,34,34, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, + { + 52,52,20,20,3,3,3,3,11,11,11,11,27,27,27,27, + 35,35,35,35,43,43,43,43,58,58,58,58,58,58,58,58, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}; + +static const short g9HuffLookupTable[2][50] = {{ + 13,29,37,61,20,20,68,68,3,3,3,3,51,51,51,51, + 41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0 }, + { + -32736,53,28,28,11,11,11,11,19,19,19,19,43,43,43,43, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + -32734,4,7,8,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0 }}; + +static const short g12HuffLookupTable[5][56] = {{ + -32736,5,76,76,37,53,69,85,43,43,43,43,91,91,91,91, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + -32734,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 }, + { + -32736,85,13,53,4,4,36,36,43,43,43,43,67,67,67,67, + 75,75,75,75,91,91,91,91,58,58,58,58,58,58,58,58, + 2,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 }, + { + -32736,37,92,92,11,11,11,11,43,43,43,43,59,59,59,59, + 67,67,67,67,75,75,75,75,2,2,2,2,2,2,2,2, + -32734,-32732,2,3,6,10,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 }, + { + -32736,29,37,69,3,3,3,3,43,43,43,43,59,59,59,59, + 75,75,75,75,91,91,91,91,10,10,10,10,10,10,10,10, + -32734,10,2,6,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 }, + { + -32736,93,28,28,60,60,76,76,3,3,3,3,43,43,43,43, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + -32734,-32732,-32730,2,4,8,6,10,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 }}; + +/********************************************************************** + Allocation and dellocation +**********************************************************************/ +Void Clean (CAdaptiveHuffman *pAdHuff) +{ + if (pAdHuff == NULL) + return; + free (pAdHuff); +} + +CAdaptiveHuffman *Allocate (Int iNSymbols, CODINGMODE cm) +{ + CAdaptiveHuffman *pAdHuff = (CAdaptiveHuffman *) malloc (sizeof (CAdaptiveHuffman)); + + UNREFERENCED_PARAMETER(cm); + + if (pAdHuff == NULL) + return NULL; + if (iNSymbols > 255 || iNSymbols <= 0) + goto ErrorExit; + + memset (pAdHuff, 0, sizeof (CAdaptiveHuffman)); + pAdHuff->m_iNSymbols = iNSymbols; + + pAdHuff->m_pDelta = NULL; + pAdHuff->m_iDiscriminant = pAdHuff->m_iUpperBound = pAdHuff->m_iLowerBound = 0; + + return pAdHuff; + +ErrorExit: + Clean (pAdHuff); + return NULL; +} + +/********************************************************************** + Adapt Huffman table +**********************************************************************/ +// Alphabet size = 4 +static const Int g_Index4Table[] = { + 1,2,3,3 +}; +static const Int g4CodeTable[] = { + 4, + 1, 1, + 1, 2, + 0, 3, + 1, 3 +}; + +// Alphabet size = 5 +static const Int g_Index5Table[] = { + 1,2,3,4,4, + 1,3,3,3,3 +}; +static const Int g5CodeTable[] = { + 5, + 1, 1, + 1, 2, + 1, 3, + 0, 4, + 1, 4, + + 5, + 1, 1, + 0, 3, + 1, 3, + 2, 3, + 3, 3, +}; +static const Int g5DeltaTable[] = { 0,-1,0,1,1 }; + +// Alphabet size = 6 +static const Int g_Index6Table[] = { + 1,5,3,5,2,4, + 2,4,2,4,2,3, + 4,4,2,2,2,3, + 5,5,2,1,4,3, +}; +static const Int g6CodeTable[] = { + 6, + 1, 1, + 0, 5, + 1, 3, + 1, 5, + 1, 2, + 1, 4, + + 6, + 1, 2, + 0, 4, + 2, 2, + 1, 4, + 3, 2, + 1, 3, + + 6, + 0, 4, + 1, 4, + 1, 2, + 2, 2, + 3, 2, + 1, 3, + + 6, + 0, 5, + 1, 5, + 1, 2, + 1, 1, + 1, 4, + 1, 3 +}; +static const Int g6DeltaTable[] = { + -1, 1, 1, 1, 0, 1, + -2, 0, 0, 2, 0, 0, + -1,-1, 0, 1,-2, 0 +}; + +// Alphabet size = 7 +static const Int g_Index7Table[] = { 2,2,2,3,4,5,5, + 1,2,3,4,5,6,6 }; +static const Int g7CodeTable[] = { + 7, + 1, 2, + 2, 2, + 3, 2, + 1, 3, + 1, 4, + 0, 5, + 1, 5, + + 7, + 1, 1, + 1, 2, + 1, 3, + 1, 4, + 1, 5, + 0, 6, + 1, 6 +}; +static const Int g7DeltaTable[] = { 1,0,-1,-1,-1,-1,-1 }; + +// Alphabet size = 8 +static const Int g_Index8Table[] = { 2,3,5,4,2,3,5,3, + 3,3,4,3,3,3,4,2}; +static const Int g8CodeTable[] = { + 8, + 2, 2, + 1, 3, + 1, 5, + 1, 4, + 3, 2, + 2, 3, + 0, 5, + 3, 3, + + 8, + 1, 3, + 2, 3, + 1, 4, + 3, 3, + 4, 3, + 5, 3, + 0, 4, + 3, 2 +}; +static const Int g8DeltaTable[] = { -1,0,1,1,-1,0,1,1 }; + +static const Int g_Index9Table[] = { + 3,5,4,5,5,1,3,5,4, + 1,3,3,4,6,3,5,7,7, +}; +static const Int g9CodeTable[] = { + 9, + 2, 3, + 0, 5, + 2, 4, + 1, 5, + 2, 5, + 1, 1, + 3, 3, + 3, 5, + 3, 4, + + 9, + 1, 1, + 1, 3, + 2, 3, + 1, 4, + 1, 6, + 3, 3, + 1, 5, + 0, 7, + 1, 7, +}; +static const Int g9DeltaTable[] = { 2,2,1,1,-1,-2,-2,-2,-3 }; + +// Alphabet size = 12 +static const Int g_Index12Table[] = { // index12 is the most critical symbol + 5,6,7,7,5,3,5,1,5,4,5,3, + 4,5,6,6,4,3,5,2,3,3,5,3, + 2,3,7,7,5,3,7,3,3,3,7,4, + 3,2,7,5,5,3,7,3,5,3,6,3, + 3,1,7,4,7,3,8,4,7,4,8,5, +}; +static const Int g12CodeTable[] = { + 12, + 1, 5, + 1, 6, + 0, 7, + 1, 7, + 4, 5, + 2, 3, + 5, 5, + 1, 1, + 6, 5, + 1, 4, + 7, 5, + 3, 3, + + 12, + 2, 4, + 2, 5, + 0, 6, + 1, 6, + 3, 4, + 2, 3, + 3, 5, + 3, 2, + 3, 3, + 4, 3, + 1, 5, + 5, 3, + + 12, + 3, 2, + 1, 3, + 0, 7, + 1, 7, + 1, 5, + 2, 3, + 2, 7, + 3, 3, + 4, 3, + 5, 3, + 3, 7, + 1, 4, + + 12, + 1, 3, + 3, 2, + 0, 7, + 1, 5, + 2, 5, + 2, 3, + 1, 7, + 3, 3, + 3, 5, + 4, 3, + 1, 6, + 5, 3, + + 12, + 2, 3, + 1, 1, + 1, 7, + 1, 4, + 2, 7, + 3, 3, + 0, 8, + 2, 4, + 3, 7, + 3, 4, + 1, 8, + 1, 5 +}; +static const Int g12DeltaTable[] = { + 1, 1, 1, 1, 1, 0, 0,-1, 2, 1, 0, 0, + 2, 2,-1,-1,-1, 0,-2,-1, 0, 0,-2,-1, + -1, 1, 0, 2, 0, 0, 0, 0,-2, 0, 1, 1, + 0, 1, 0, 1,-2, 0,-1,-1,-2,-1,-2,-2 +}; + +/********************************************************************** + Adapt fixed length codes based on discriminant +**********************************************************************/ +static const Int THRESHOLD = 8; +static const Int MEMORY = 8; + +Void AdaptDiscriminant (CAdaptiveHuffman *pAdHuff) +{ + Int iSym = pAdHuff->m_iNSymbols, t, dL, dH; + const Int *pCodes, *pDelta = NULL; + Bool bChange = FALSE; + static const Int gMaxTables[] = { 0,0,0,0, 1,2, 4,2, 2,2, 0,0,5 }; + static const Int gSecondDisc[]= { 0,0,0,0, 0,0, 1,0, 0,0, 0,0,1 }; + + if (!pAdHuff->m_bInitialize) { + pAdHuff->m_bInitialize = 1; + pAdHuff->m_iDiscriminant = pAdHuff->m_iDiscriminant1 = 0; + pAdHuff->m_iTableIndex = gSecondDisc[iSym];//(gMaxTables[iSym] - 1) >> 1; + } + + dL = dH = pAdHuff->m_iDiscriminant; + if (gSecondDisc[iSym]) { + dH = pAdHuff->m_iDiscriminant1; + } + + if (dL < pAdHuff->m_iLowerBound) { + pAdHuff->m_iTableIndex--; + bChange = TRUE; + } + else if (dH > pAdHuff->m_iUpperBound) { + pAdHuff->m_iTableIndex++; + bChange = TRUE; + } + if (bChange) { + /** if initialization is fixed, we can exit on !bChange **/ + pAdHuff->m_iDiscriminant = 0; + pAdHuff->m_iDiscriminant1 = 0; + } + { + if (pAdHuff->m_iDiscriminant < -THRESHOLD * MEMORY) + pAdHuff->m_iDiscriminant = -THRESHOLD * MEMORY; + else if (pAdHuff->m_iDiscriminant > THRESHOLD * MEMORY) + pAdHuff->m_iDiscriminant = THRESHOLD * MEMORY; + + if (pAdHuff->m_iDiscriminant1 < -THRESHOLD * MEMORY) + pAdHuff->m_iDiscriminant1 = -THRESHOLD * MEMORY; + else if (pAdHuff->m_iDiscriminant1 > THRESHOLD * MEMORY) + pAdHuff->m_iDiscriminant1 = THRESHOLD * MEMORY; + } + + t = pAdHuff->m_iTableIndex; + assert (t >= 0); + assert (t < gMaxTables[iSym]); + + //pAdHuff->m_iDiscriminant >>= 1; + pAdHuff->m_iLowerBound = (t == 0) ? (-1 << 31) : -THRESHOLD; + pAdHuff->m_iUpperBound = (t == gMaxTables[iSym] - 1) ? (1 << 30) : THRESHOLD; + + switch (iSym) { + case 4: + pCodes = g4CodeTable; + pAdHuff->m_hufDecTable = (short *) g4HuffLookupTable; + break; + case 5: + pCodes = g5CodeTable + (iSym * 2 + 1) * t; + pDelta = g5DeltaTable; + pAdHuff->m_hufDecTable = g5HuffLookupTable[t]; + break; + case 6: + pCodes = g6CodeTable + (iSym * 2 + 1) * t; + pAdHuff->m_pDelta1 = g6DeltaTable + iSym * (t - (t + 1 == gMaxTables[iSym])); + pDelta = g6DeltaTable + (t - 1 + (t == 0)) * iSym; + pAdHuff->m_hufDecTable = g6HuffLookupTable[t]; + break; + case 7: + pCodes = g7CodeTable + (iSym * 2 + 1) * t; + pDelta = g7DeltaTable; + pAdHuff->m_hufDecTable = g7HuffLookupTable[t]; + break; + case 8: + //printf ("%d ", t); + pCodes = g8CodeTable;// + (iSym * 2 + 1) * t; + //pDelta = g8DeltaTable; + pAdHuff->m_hufDecTable = g8HuffLookupTable[0]; + break; + case 9: + pCodes = g9CodeTable + (iSym * 2 + 1) * t; + pDelta = g9DeltaTable; + pAdHuff->m_hufDecTable = g9HuffLookupTable[t]; + break; + case 12: + pCodes = g12CodeTable + (iSym * 2 + 1) * t; + pAdHuff->m_pDelta1 = g12DeltaTable + iSym * (t - (t + 1 == gMaxTables[iSym])); + pDelta = g12DeltaTable + (t - 1 + (t == 0)) * iSym; + pAdHuff->m_hufDecTable = g12HuffLookupTable[t]; + break; + default: + assert (0); // undefined fixed length table + return; + } + + pAdHuff->m_pTable = pCodes; + pAdHuff->m_pDelta = pDelta; +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/adapthuff.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/adapthuff.o new file mode 100644 index 0000000..664663e Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/adapthuff.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/ansi.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/ansi.h new file mode 100644 index 0000000..5d2b213 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/ansi.h @@ -0,0 +1,69 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#pragma once + +//================================ +// bitio functions +//================================ +#define PACKETLENGTH (1U<<12) // 4kB + +#define readIS_L1(pSC, pIO) readIS(pSC, pIO) +#define readIS_L2(pSC, pIO) (void)(pSC, pIO) + +#define writeIS_L1(pSC, pIO) writeIS(pSC, pIO) +#define writeIS_L2(pSC, pIO) (void)(pSC, pIO) + + +//================================ +// common defines +//================================ +#define FORCE_INLINE +#define CDECL + +// Note these are modified from the original library, +// which made its own defs that were wrong on Linux. +#include +#define UINTPTR_T uintptr_t +#define INTPTR_T intptr_t + + +//================================ +// quantization optimization +//================================ +//#define RECIP_QUANT_OPT + + +//================================ +// For big-endian Linux; not tested +//================================ +#ifdef __linux__ +#include +#if __BYTE_ORDER == __BIG_ENDIAN +#define _BIG__ENDIAN_ +#endif +#endif diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/common.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/common.h new file mode 100644 index 0000000..80679ad --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/common.h @@ -0,0 +1,131 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#ifndef WMI_COMMON_H +#define WMI_COMMON_H + +/************************************************************************* +// Common typedef's +*************************************************************************/ +typedef enum { ENCODER = 0, DECODER = 1 } CODINGMODE; + +typedef enum tagBand +{ + BAND_HEADER = 0, + BAND_DC = 1, + BAND_LP = 2, + BAND_AC = 3, + BAND_FL = 4 +} BAND; + +/************************************************************************* + struct / class definitions +*************************************************************************/ +//#define SIGNATURE_BYTES 8 // Bytes for GDI+ signature +#define CODEC_VERSION 1 +#define CODEC_SUBVERSION 0 +#define CODEC_SUBVERSION_NEWSCALING_SOFT_TILES 1 +#define CODEC_SUBVERSION_NEWSCALING_HARD_TILES 9 + +#define CONTEXTX 8 +#define CTDC 5 +#define NUMVLCTABLES 21 // CONTEXTX * 2 + CTDC +#define AVG_NDIFF 3 + +#define MAXTOTAL 32767 // 511 should be enough + +/** Quantization related defines **/ +#define SHIFTZERO 1 /* >= 0 */ +#define QPFRACBITS 2 /* or 0 only supported */ + +/** adaptive huffman encoding / decoding struct **/ +typedef struct CAdaptiveHuffman +{ + Int m_iNSymbols; + const Int *m_pTable; + const Int *m_pDelta, *m_pDelta1; + Int m_iTableIndex; + const short *m_hufDecTable; + Bool m_bInitialize; + //Char m_pLabel[8]; // for debugging - label attached to constructor + + Int m_iDiscriminant, m_iDiscriminant1; + Int m_iUpperBound; + Int m_iLowerBound; +} CAdaptiveHuffman; + + +/************************************************************************************ + Context structures +************************************************************************************/ +typedef struct CAdaptiveModel { + Int m_iFlcState[2]; + Int m_iFlcBits[2]; + BAND m_band; +} CAdaptiveModel; + +typedef struct CCBPModel { + Int m_iCount0[2]; + Int m_iCount1[2]; + Int m_iState[2]; +} CCBPModel; + +/************************************************************************* + globals +*************************************************************************/ +extern Int grgiZigzagInv4x4_lowpass[]; +extern Int grgiZigzagInv4x4H[]; +extern Int grgiZigzagInv4x4V[]; +extern const Int gSignificantRunBin[]; +extern const Int gSignificantRunFixedLength[]; +static const Int cblkChromas[] = {0,4,8,16, 16,16,16, 0,0}; +/************************************************************************* + function declarations +*************************************************************************/ +// common utilities +Void Clean (CAdaptiveHuffman *pAdHuff); +CAdaptiveHuffman *Allocate (Int iNSymbols, CODINGMODE cm); + +/* Timing functions */ +void reset_timing(double *time); +void report_timing(const char *s, double time); +// static double timeperclock; + +/** adaptive model functions **/ +Void UpdateModelMB (COLORFORMAT cf, Int iChannels, Int iLaplacianMean[], CAdaptiveModel *m_pModel); + +/** adaptive huffman encoder / decoder functions **/ +Void Adapt (CAdaptiveHuffman *pAdHuff, Bool bFixedTables); +Void AdaptFixed (CAdaptiveHuffman *pAdHuff); +Void AdaptDiscriminant (CAdaptiveHuffman *pAdHuff); + +#ifndef _PREFAST_ +#pragma warning(disable:4068) +#endif + +#endif // WMI_COMMON_H diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/image.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/image.c new file mode 100644 index 0000000..5605abc --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/image.c @@ -0,0 +1,183 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strcodec.h" +// #include "xplatform_image.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +#include +#include + +#if !(defined(__ANSI__)) +// Desktop +#include +#else +// ANSI +#include +#endif + +Int grgiZigzagInv4x4_lowpass [] = { + 0, 1, 4, 5, 2, 8, 6, 9, + 3, 12, 10, 7, 13, 11, 14, 15 +}; + +Int grgiZigzagInv4x4H [] = { + 0, 1, 4, 5, 2, 8, 6, 9, + 3, 12, 10, 7, 13, 11, 14, 15 +}; +Int grgiZigzagInv4x4V [] = { + 0, 4, 8, 5, 1, 12, 9, 6, 2, 13, 3, 15, 7, 10, 14, 11 +}; + +const Int gSignificantRunBin[] = { + -1,-1,-1,-1, + 2,2,2, + 1,1,1,1, + 0,0,0,0 +}; + +const Int gSignificantRunFixedLength[] = { + 0,0,1,1,3, + 0,0,1,1,2, + 0,0,0,0,1, +}; + +/************************************************************************* + UpdateModelMB : update adaptive model at end of macroblock + (for lowest resolution only) +*************************************************************************/ +#define MODELWEIGHT 70//90 + +Void UpdateModelMB (COLORFORMAT cf, Int iChannels, Int iLaplacianMean[], CAdaptiveModel *pModel) +{ + Int j; + static const Int aWeight0[3] = { 240/*DC*/, 12/*LP*/, 1 }; + static const Int aWeight1[3][MAX_CHANNELS] = { + { 0,240,120,80, 60,48,40,34, 30,27,24,22, 20,18,17,16 }, + { 0,12,6,4, 3,2,2,2, 2,1,1,1, 1,1,1,1 }, + { 0,16,8,5, 4,3,3,2, 2,2,2,1, 1,1,1,1 } + }; + static const Int aWeight2[6] = { 120,37,2,/*420*/ 120,18,1/*422*/ }; + + iLaplacianMean[0] *= aWeight0[pModel->m_band - BAND_DC]; + if (cf == YUV_420) { + iLaplacianMean[1] *= aWeight2[pModel->m_band - BAND_DC]; + } + else if (cf == YUV_422) { + iLaplacianMean[1] *= aWeight2[3 + (pModel->m_band) - BAND_DC]; + } + else { + iLaplacianMean[1] *= aWeight1[pModel->m_band - BAND_DC][iChannels - 1]; + if (pModel->m_band == BAND_AC) + iLaplacianMean[1] >>= 4; + } + + for (j = 0; j < 2; j++) { + Int iLM = iLaplacianMean[j]; + Int iMS = pModel->m_iFlcState[j]; + Int iDelta = (iLM - MODELWEIGHT) >> 2; + + if (iDelta <= -8) { + iDelta += 4; + if (iDelta < -16) + iDelta = -16; + iMS += iDelta; + if (iMS < -8) { + if (pModel->m_iFlcBits[j] == 0) + iMS = -8; + else { + iMS = 0; + pModel->m_iFlcBits[j]--; + } + } + } + else if (iDelta >= 8) { + iDelta -= 4; + if (iDelta > 15) + iDelta = 15; + iMS += iDelta; + if (iMS > 8) { + if (pModel->m_iFlcBits[j] >= 15) { + pModel->m_iFlcBits[j] = 15; + iMS = 8; + } + else { + iMS = 0; + pModel->m_iFlcBits[j]++; + } + } + } + pModel->m_iFlcState[j] = iMS; + if (cf == Y_ONLY) + break; + } +} + + +Void ResetCodingContext(CCodingContext *pContext) +{ + // reset bit reduction models + memset (&(pContext->m_aModelAC), 0, sizeof(CAdaptiveModel)); + pContext->m_aModelAC.m_band = BAND_AC; + + memset (&(pContext->m_aModelLP), 0, sizeof(CAdaptiveModel)); + pContext->m_aModelLP.m_band = BAND_LP; + pContext->m_aModelLP.m_iFlcBits[0] = pContext->m_aModelLP.m_iFlcBits[1] = 4; + + memset (&(pContext->m_aModelDC), 0, sizeof(CAdaptiveModel)); + pContext->m_aModelDC.m_band = BAND_DC; + pContext->m_aModelDC.m_iFlcBits[0] = pContext->m_aModelDC.m_iFlcBits[1] = 8; + + // reset CBP models + pContext->m_iCBPCountMax = pContext->m_iCBPCountZero = 1; + + pContext->m_aCBPModel.m_iCount0[0] = pContext->m_aCBPModel.m_iCount0[1] = -4; + pContext->m_aCBPModel.m_iCount1[0] = pContext->m_aCBPModel.m_iCount1[1] = 4; + pContext->m_aCBPModel.m_iState[0] = pContext->m_aCBPModel.m_iState[1] = 0; +} + +/************************************************************************* + Initialize zigzag scan parameters +*************************************************************************/ +Void InitZigzagScan(CCodingContext * pContext) +{ + if (NULL != pContext) { + Int i; + for (i=0; i<16; i++) { + pContext->m_aScanLowpass[i].uScan = grgiZigzagInv4x4_lowpass[i]; + pContext->m_aScanHoriz[i].uScan = dctIndex[0][grgiZigzagInv4x4H[i]]; + pContext->m_aScanVert[i].uScan = dctIndex[0][grgiZigzagInv4x4V[i]]; + } + } +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/image.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/image.o new file mode 100644 index 0000000..1c71f01 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/image.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimer.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimer.h new file mode 100644 index 0000000..f578674 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimer.h @@ -0,0 +1,115 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#ifndef __PERFTIMER_H_ +#define __PERFTIMER_H_ + +//*************************************************************************** +// Description +// +// Performance timer API used to measure codec performance. The underlying +// implementation of this API may vary - from ANSI-C implementation via clock, +// Win32 implementation via QueryPerformanceCounter or GetProcessTimes. At +// present we only support one implementation of this PerfTimer "object". +// You choose the implementation by choosing which one of the many files +// to compile and link with your application. +//*************************************************************************** + +#ifdef DISABLE_PERF_MEASUREMENT + +#define PERFTIMER_ONLY(code) +#define PERFTIMER_NEW(fPerf, ppPerfTimer) +#define PERFTIMER_DELETE(fPerf, ppPerfTimer) +#define PERFTIMER_START(fPerf, pPerfTimer) +#define PERFTIMER_STOP(fPerf, pPerfTimer) +#define PERFTIMER_GETRESULTS(fPerf, pPerfTimer, pResults) +#define PERFTIMER_COPYSTARTTIME(fPerf, pDst, pSrc) +#define PERFTIMER_REPORT(fPerf, pCodec) + +#else // DISABLE_PERF_MEASUREMENT + +#define PERFTIMER_ONLY(code) code +#define PERFTIMER_NEW(fPerf, ppPerfTimer) if (fPerf) {Bool b = b = PerfTimerNew(ppPerfTimer); assert(b);}; +#define PERFTIMER_DELETE(fPerf, pPerfTimer) if (fPerf) {PerfTimerDelete(pPerfTimer);}; +#define PERFTIMER_START(fPerf, pPerfTimer) if (fPerf) {Bool b = b = PerfTimerStart(pPerfTimer); assert(b);}; +#define PERFTIMER_STOP(fPerf, pPerfTimer) if (fPerf) {Bool b = b = PerfTimerStop(pPerfTimer); assert(b);}; +#define PERFTIMER_GETRESULTS(fPerf, pPerfTimer, pResults) \ + if (fPerf) {Bool b = b = PerfTimerGetResults((pPerfTimer), (pResults)); assert(b);}; +#define PERFTIMER_COPYSTARTTIME(fPerf, pDst, pSrc) \ + if (fPerf) {Bool b = b = PerfTimerCopyStartTime((pDst), (pSrc)); assert(b);}; +#define PERFTIMER_REPORT(fPerf, pCodec) \ + if (fPerf) {OutputPerfTimerReport(pCodec);}; +#endif // DISABLE_PERF_MEASUREMENT + +//*************************************************************************** +// Data Types +//*************************************************************************** +typedef U64 PERFTIMERTIME; +typedef struct PERFTIMERRESULTS +{ + PERFTIMERTIME iElapsedTime; // In nanoseconds or CPU cycles + PERFTIMERTIME iTicksPerSecond; // Number of ticks per second (clock frequency) + PERFTIMERTIME iZeroTimeIntervals; // Number of zero-time intervals. + // Presence of zero-time intervals may indicate insufficient clock precision +} PERFTIMERRESULTS; + +#define NANOSECONDS_PER_SECOND 1000000000 + + +//*************************************************************************** +// Data Declarations +//*************************************************************************** +typedef enum +{ + CS_UNINIT, + CS_RUNNING, + CS_STOPPED, +} CLOCKSTATE; + +typedef struct PERFTIMERSTATE +{ + CLOCKSTATE eState; + PERFTIMERTIME iElapsedTime; + PERFTIMERTIME iPrevStartTime; + PERFTIMERTIME iZeroTimeIntervals; +} PERFTIMERSTATE; + + +//*************************************************************************** +// Functions and Macros +//*************************************************************************** +Bool PerfTimerNew(PERFTIMERSTATE **ppNewPerfTimer); +void PerfTimerDelete(PERFTIMERSTATE *pThisPerfTimer); +Bool PerfTimerStart(PERFTIMERSTATE *pThisPerfTimer); +Bool PerfTimerStop(PERFTIMERSTATE *pThisPerfTimer); +Bool PerfTimerGetResults(PERFTIMERSTATE *pThisPerfTimer, + PERFTIMERRESULTS *pPerfTimerResults); +Bool PerfTimerCopyStartTime(PERFTIMERSTATE *pDestPerfTimer, + PERFTIMERSTATE *pSrcPerfTimer); + +#endif // __PERFTIMER_H_ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimerANSI.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimerANSI.c new file mode 100644 index 0000000..20e71b2 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimerANSI.c @@ -0,0 +1,274 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +//*************************************************************************** +// Includes +//*************************************************************************** +#include +#include "strcodec.h" +#include "perfTimer.h" + + +#ifndef DISABLE_PERF_MEASUREMENT + + +//*************************************************************************** +// Private Functions +//*************************************************************************** + +Bool AccumulateTime(PERFTIMERSTATE *pState, PERFTIMERTIME *ptAccumulator) +{ + Bool fResult = FALSE; + clock_t iStopTime; + clock_t iIntervalTime; + iStopTime = clock(); + + // Check clock result + if ((clock_t)-1 == iStopTime) + { + TraceResult(WM_E_CLOCKFAILURE); + goto exit; + } + + iIntervalTime = (iStopTime - (clock_t) pState->iPrevStartTime); + + // Check for zero-time interval + if (0 == iIntervalTime) + pState->iZeroTimeIntervals += 1; + + // Accumulate current interval's time + *ptAccumulator += iIntervalTime; + fResult = TRUE; + +exit: + return fResult; +} + + +//*************************************************************************** +// Public Functions +//*************************************************************************** + + +Bool PerfTimerNew(PERFTIMERSTATE **ppNewPerfTimer) +{ + Bool fResult = FALSE; + PERFTIMERSTATE *pState = NULL; + clock_t ctResult; + + // Check if this clock works + ctResult = clock(); + if ((clock_t)-1 == ctResult) + { + TraceResult(WM_E_CLOCKFAILURE); + goto exit; + } + + pState = malloc(sizeof(*pState)); + if (NULL == pState) + { + TraceResult(E_OUTOFMEMORY); + goto exit; + } + memset(pState, 0, sizeof(*pState)); + pState->eState = CS_STOPPED; + pState->iElapsedTime = 0; + pState->iPrevStartTime = 0; + pState->iZeroTimeIntervals = 0; + + *ppNewPerfTimer = pState; + fResult = TRUE; + +exit: + assert(fResult || NULL == pState); // If error, we need to free pState + return fResult; +} // PerfTimerNew + + + +void PerfTimerDelete(PERFTIMERSTATE *pState) +{ + free(pState); +} // PerfTimerDelete + + + +Bool PerfTimerStart(PERFTIMERSTATE *pState) +{ + Bool fResult = FALSE; + + if (NULL == pState) + { + // Can happen because we typically ignore errors and use a single bool to + // control all perf timing (some of which can fail to init) + goto exit; + } + + // Make sure we are in the right state + if (CS_STOPPED != pState->eState) + { + assert(FALSE); + goto exit; + } + + pState->iPrevStartTime = clock(); + + // Check clock result + if ((clock_t)-1 == pState->iPrevStartTime) + { + TraceResult(WM_E_CLOCKFAILURE); + goto exit; + } + + pState->eState = CS_RUNNING; + fResult = TRUE; + +exit: + return fResult; +} // PerfTimerStart + + + +Bool PerfTimerStop(PERFTIMERSTATE *pState) +{ + Bool fResult = FALSE; + + if (NULL == pState) + { + // Can happen because we typically ignore errors and use a single bool to + // control all perf timing (some of which can fail to init) + goto exit; + } + + // Make sure we are in the right state + if (CS_RUNNING != pState->eState) + { + assert(FALSE); + goto exit; + } + + fResult = AccumulateTime(pState, &pState->iElapsedTime); + pState->eState = CS_STOPPED; + fResult = TRUE; + +exit: + return fResult; +} // PerfTimerStop + + + +Bool PerfTimerGetResults(PERFTIMERSTATE *pState, PERFTIMERRESULTS *pResults) +{ + Bool fResult = FALSE; + PERFTIMERTIME iElapsedTime; + + if (NULL == pState) + { + // Can happen because we typically ignore errors and use a single bool to + // control all perf timing (some of which can fail to init) + goto exit; + } + + // Make sure we are in the right state + if (CS_STOPPED != pState->eState && CS_RUNNING != pState->eState) + { + assert(FALSE); + goto exit; + } + + iElapsedTime = pState->iElapsedTime; + if (CS_RUNNING == pState->eState) + { + // Must take a "checkpoint" time reading + fResult = AccumulateTime(pState, &iElapsedTime); + if (FALSE == fResult) + goto exit; + } + + // Convert clock ticks to nanoseconds. + // Use floating point for ease of math. If your platform really blows + // with floating point, replace this with appropriate integer calculation + // based on your clock interval. + pResults->iElapsedTime = (PERFTIMERTIME)((float)iElapsedTime * + ((float)NANOSECONDS_PER_SECOND / (float)CLOCKS_PER_SEC)); + pResults->iTicksPerSecond = CLOCKS_PER_SEC; + pResults->iZeroTimeIntervals = pState->iZeroTimeIntervals; + fResult = TRUE; + +exit: + return fResult; +} // PerfTimerGetResults + + + +Bool PerfTimerCopyStartTime(PERFTIMERSTATE *pDestPerfTimer, + PERFTIMERSTATE *pSrcPerfTimer) +{ + Bool fResult = FALSE; + + if (NULL == pDestPerfTimer) + { + TraceResult(E_INVALIDARG); + goto exit; + } + + if (NULL == pSrcPerfTimer) + { + TraceResult(E_INVALIDARG); + goto exit; + } + + // Check that both timers are in proper state - both must be running + if (CS_RUNNING != pDestPerfTimer->eState) + { + TraceResult(WM_E_INVALIDSTATE); + goto exit; + } + + if (CS_RUNNING != pSrcPerfTimer->eState) + { + TraceResult(WM_E_INVALIDSTATE); + goto exit; + } + + if (0 != pDestPerfTimer->iElapsedTime) + { + // If iElapsedTime is non-zero, caller won't get what he is expecting + // when he calls PerfTimerGetResults + TraceResult(WM_E_INVALIDSTATE); + goto exit; + } + + pDestPerfTimer->iPrevStartTime = pSrcPerfTimer->iPrevStartTime; + fResult = TRUE; + +exit: + return fResult; +} // PerfTimerCopyStartTime + +#endif // DISABLE_PERF_MEASUREMENT diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimerANSI.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimerANSI.o new file mode 100644 index 0000000..75171a9 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/perfTimerANSI.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strPredQuant.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strPredQuant.c new file mode 100644 index 0000000..3092d23 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strPredQuant.c @@ -0,0 +1,306 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strcodec.h" + +#define ORIENT_WEIGHT 4 + +/* reciprocal (pMantissa, exponent) lookup table */ +typedef struct tagQPManExp +{ + int iMan; + int iExp; +} QPManExp; + +static QPManExp gs_QPRecipTable[32] = { + {0x0, 0}, // 0, invalid + {0x0, 0}, // 1, lossless + {0x0, 1}, // 2 + {0xaaaaaaab, 1}, + {0x0, 2}, // 4 + {0xcccccccd, 2}, + {0xaaaaaaab, 2}, + {0x92492493, 2}, + {0x0, 3}, // 8 + {0xe38e38e4, 3}, + {0xcccccccd, 3}, + {0xba2e8ba3, 3}, + {0xaaaaaaab, 3}, + {0x9d89d89e, 3}, + {0x92492493, 3}, + {0x88888889, 3}, + {0x0, 4}, // 16 + {0xf0f0f0f1, 4}, + {0xe38e38e4, 4}, + {0xd79435e6, 4}, + {0xcccccccd, 4}, + {0xc30c30c4, 4}, + {0xba2e8ba3, 4}, + {0xb21642c9, 4}, + {0xaaaaaaab, 4}, + {0xa3d70a3e, 4}, + {0x9d89d89e, 4}, + {0x97b425ee, 4}, + {0x92492493, 4}, + {0x8d3dcb09, 4}, + {0x88888889, 4}, + {0x84210843, 4}, +}; + +/************************************************************************* + QPRemapping +*************************************************************************/ + +Void remapQP(CWMIQuantizer * pQP, I32 iShift, Bool bScaledArith) +{ + U8 uiQPIndex = pQP->iIndex; + + if(uiQPIndex == 0) // Lossless mode! + pQP->iQP = 1, pQP->iMan = pQP->iExp = pQP->iOffset = 0; + else if (!bScaledArith) { + I32 man = 0, exp = 0; + const I32 ciShift = SHIFTZERO - (SHIFTZERO + QPFRACBITS); // == -QPFRACBITS + + if (pQP->iIndex < 32) + man = (pQP->iIndex + 3) >> 2, exp = ciShift + 2; + else if (pQP->iIndex < 48) + man = (16 + (pQP->iIndex & 0xf) + 1) >> 1, exp = ((pQP->iIndex >> 4) - 1) + 1 + ciShift; + else + man = 16 + (pQP->iIndex & 0xf), exp = ((pQP->iIndex >> 4) - 1) + ciShift; + + pQP->iQP = man << exp; + pQP->iMan = gs_QPRecipTable[man].iMan; + pQP->iExp = gs_QPRecipTable[man].iExp + exp; + pQP->iOffset = ((pQP->iQP * 3 + 1) >> 3); +#if defined(WMP_OPT_QT) + pQP->f1_QP = 1.0f / pQP->iQP; + pQP->d1_QP = 1.0 / pQP->iQP; +#endif + } + else { + I32 man = 0, exp = 0; + + if(pQP->iIndex < 16) + man = pQP->iIndex, exp = iShift; + else + man = 16 + (pQP->iIndex & 0xf), exp = ((pQP->iIndex >> 4) - 1) + iShift; + + pQP->iQP = man << exp; + pQP->iMan = gs_QPRecipTable[man].iMan; + pQP->iExp = gs_QPRecipTable[man].iExp + exp; + pQP->iOffset = ((pQP->iQP * 3 + 1) >> 3); +#if defined(WMP_OPT_QT) + pQP->f1_QP = 1.0f / pQP->iQP; + pQP->d1_QP = 1.0 / pQP->iQP; +#endif + } +} + +/* allocate PredInfo buffers */ +Int allocatePredInfo(CWMImageStrCodec *pSC) +{ + size_t i, j; + // COLORFORMAT cf = pSC->m_param.cfColorFormat; + const size_t mbWidth = pSC->cmbWidth; + const size_t iChannels = pSC->m_param.cNumChannels; + CWMIPredInfo* pMemory; + Bool b32Bit = sizeof(size_t) == 4; + + if(b32Bit) // integer overlow/underflow check for 32-bit system + if(((mbWidth >> 16) * iChannels * 2 * sizeof(CWMIPredInfo)) & 0xffff0000) + return ICERR_ERROR; + pMemory = (CWMIPredInfo *)malloc(mbWidth * iChannels * 2 * sizeof(CWMIPredInfo)); + if (pMemory == NULL) + return ICERR_ERROR; + + pSC->pPredInfoMemory = pMemory; + for(i = 0; i < iChannels; i ++){ + pSC->PredInfo[i] = pMemory; + pMemory += mbWidth; + pSC->PredInfoPrevRow[i] = pMemory; + pMemory += mbWidth; + + for(j = 0; j < mbWidth; j ++){ + pSC->PredInfo[i][j].piAD = pSC->PredInfo[i][j].iAD; + pSC->PredInfoPrevRow[i][j].piAD = pSC->PredInfoPrevRow[i][j].iAD; + } + } + + return ICERR_OK; +} + +/* clear PredInfo buffers */ +Void freePredInfo(CWMImageStrCodec *pSC) +{ + if (pSC->pPredInfoMemory) + free (pSC->pPredInfoMemory); + pSC->pPredInfoMemory = NULL; +} + +/* get AC prediction mode: 0(from left) 1(from top) 2(none) */ +Int getACPredMode(CWMIMBInfo * pMBInfo, COLORFORMAT cf) +{ + //Int blkIdx = (cf == Y_ONLY ? 16 : (cf == YUV_420 ? 24 : (cf == YUV_422 ? 32 : 48))); + PixelI * pCoeffs = pMBInfo->iBlockDC[0]; + Int StrH = abs(pCoeffs[1]) + abs(pCoeffs[2]) + abs(pCoeffs[3]); + Int StrV = abs(pCoeffs[4]) + abs(pCoeffs[8]) + abs(pCoeffs[12]); + + if(cf != Y_ONLY && cf != NCOMPONENT){ + PixelI * pCoeffsU = pMBInfo->iBlockDC[1]; + PixelI * pCoeffsV = pMBInfo->iBlockDC[2]; + + StrH += abs(pCoeffsU[1]) + abs(pCoeffsV[1]); + if(cf == YUV_420){ + StrV += abs(pCoeffsU[2]) + abs(pCoeffsV[2]); + } + else if (cf == YUV_422){ + StrV += abs(pCoeffsU[2]) + abs(pCoeffsV[2]) + abs(pCoeffsU[6]) + abs(pCoeffsV[6]); + StrH += abs(pCoeffsU[5]) + abs(pCoeffsV[5]); + } + else { // YUV_444 or CMYK + StrV += abs(pCoeffsU[4]) + abs(pCoeffsV[4]); + } + } + + return (StrH * ORIENT_WEIGHT < StrV ? 1 : (StrV * ORIENT_WEIGHT < StrH ? 0 : 2)); +} + +/* get DCAC prediction mode: 0(from left) 1(from top) 2(none) */ +Int getDCACPredMode(CWMImageStrCodec *pSC, size_t mbX) +{ + Int iDCMode, iADMode = 2; // DC: 0(left) 1(top) 2(mean) 3(no) + // AD: 0(left) 1(top) 2(no) + + if(pSC->m_bCtxLeft && pSC->m_bCtxTop){ // topleft corner, no prediction + iDCMode = 3; + } + else if(pSC->m_bCtxLeft){ + iDCMode = 1; // left column, predict from top + } + else if(pSC->m_bCtxTop){ + iDCMode = 0; // top row, predict from left + } + else{ + COLORFORMAT cf = pSC->m_param.cfColorFormat; + Int iL = pSC->PredInfo[0][mbX - 1].iDC, iT = pSC->PredInfoPrevRow[0][mbX].iDC, iTL = pSC->PredInfoPrevRow[0][mbX - 1].iDC; + Int StrH, StrV; + + if(cf == Y_ONLY || cf == NCOMPONENT){ // CMYK uses YUV metric + StrH = abs(iTL - iL); + StrV = abs(iTL - iT); + } + else{ + CWMIPredInfo * pTU = pSC->PredInfoPrevRow[1] + mbX, * pLU = pSC->PredInfo[1] + mbX - 1, * pTLU = pTU - 1; + CWMIPredInfo * pTV = pSC->PredInfoPrevRow[2] + mbX, * pLV = pSC->PredInfo[2] + mbX - 1, * pTLV = pTV - 1; + Int scale = (cf == YUV_420 ? 8 : (cf == YUV_422 ? 4 : 2)); + + StrH = abs(iTL - iL) * scale + abs(pTLU->iDC - pLU->iDC) + abs(pTLV->iDC - pLV->iDC); + StrV = abs(iTL - iT) * scale + abs(pTLU->iDC - pTU->iDC) + abs(pTLV->iDC - pTV->iDC); + } + iDCMode = (StrH * ORIENT_WEIGHT < StrV ? 1 : (StrV * ORIENT_WEIGHT < StrH ? 0 : 2)); + } + + if(iDCMode == 1 && pSC->MBInfo.iQIndexLP == pSC->PredInfoPrevRow[0][mbX].iQPIndex) + iADMode = 1; + if(iDCMode == 0 && pSC->MBInfo.iQIndexLP == pSC->PredInfo[0][mbX - 1].iQPIndex) + iADMode = 0; + + return (iDCMode + (iADMode << 2)); +} + +Void copyAC(PixelI * src, PixelI * dst) +{ + /* first row of ACs */ + dst[0] = src[1]; + dst[1] = src[2]; + dst[2] = src[3]; + + /* first column of ACs */ + dst[3] = src[4]; + dst[4] = src[8]; + dst[5] = src[12]; +} + +/* info of current MB to be saved for future prediction */ +Void updatePredInfo(CWMImageStrCodec *pSC, CWMIMBInfo * pMBInfo, size_t mbX, COLORFORMAT cf) +{ + CWMIPredInfo *pPredInfo; + PixelI * p; + Int i, iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : (Int) pSC->m_param.cNumChannels; + + for(i = 0; i < iChannels; i ++){ + pPredInfo = pSC->PredInfo[i] + mbX; + p = pMBInfo->iBlockDC[i];//[dcBlkIdx + i]; + + /* DC of DC block */ + pPredInfo->iDC = p[0]; + + /* QP Index */ + pPredInfo->iQPIndex = pMBInfo->iQIndexLP; + + /* first row and first column of ACs of DC block */ + copyAC(p, pPredInfo->piAD); + } + + if(cf == YUV_420){ // 420 UV channels + for(i = 1U; i < 3U; i ++){ + pPredInfo = pSC->PredInfo[i] + mbX; + p = pMBInfo->iBlockDC[i];//[dcBlkIdx + i]; + + /* DC of DC block */ + pPredInfo->iDC = p[0]; + + /* QP Index */ + pPredInfo->iQPIndex = pMBInfo->iQIndexLP; + /* first row and first column of ACs of DC block */ + pPredInfo->piAD[0] = p[1]; + pPredInfo->piAD[1] = p[2]; + } + } + else if(cf == YUV_422){ // 420 UV channels + for(i = 1U; i < 3U; i ++){ + pPredInfo = pSC->PredInfo[i] + mbX; + + /* QP Index */ + pPredInfo->iQPIndex = pMBInfo->iQIndexLP; + + p = pMBInfo->iBlockDC[i];//[dcBlkIdx + i]; + + /* DC of DC block */ + pPredInfo->iDC = p[0]; + + /* first row and first column of ACs of first DC block */ + pPredInfo->piAD[0] = p[1]; + pPredInfo->piAD[1] = p[2]; + /* first row and first column of ACs of second DC block */ + pPredInfo->piAD[2] = p[5]; + pPredInfo->piAD[3] = p[6]; + pPredInfo->piAD[4] = p[4]; //AC of 1D HT!!! + } + } +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strPredQuant.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strPredQuant.o new file mode 100644 index 0000000..e0f4991 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strPredQuant.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.c new file mode 100644 index 0000000..57ec87a --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.c @@ -0,0 +1,85 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#include "strTransform.h" + +/** need to swap b and c **/ +/** rounding behavior: [0 0 0 0] <-> [+ - - -] + [+ + + +] <-> [+3/4 - - -] + [- - - -] <-> [- - - -] **/ +Void strDCT2x2dn(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, C, t; + a = *pa; + b = *pb; + C = *pc; + d = *pd; + + a += d; + b -= C; + t = ((a - b) >> 1); + c = t - d; + d = t - C; + a -= d; + b += c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +Void strDCT2x2up(PixelI *pa, PixelI *pb, PixelI *pc, PixelI *pd) +{ + PixelI a, b, c, d, C, t; + a = *pa; + b = *pb; + C = *pc; + d = *pd; + + a += d; + b -= C; + t = ((a - b + 1) >> 1); + c = t - d; + d = t - C; + a -= d; + b += c; + + *pa = a; + *pb = b; + *pc = c; + *pd = d; +} + +Void FOURBUTTERFLY_HARDCODED1(PixelI *p) +{ + strDCT2x2dn(&p[0], &p[4], &p[8], &p[12]); + strDCT2x2dn(&p[1], &p[5], &p[9], &p[13]); + strDCT2x2dn(&p[2], &p[6], &p[10], &p[14]); + strDCT2x2dn(&p[3], &p[7], &p[11], &p[15]); +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.h new file mode 100644 index 0000000..4fb1388 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.h @@ -0,0 +1,50 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#ifndef WMI_STRTRANSFORM_H +#define WMI_STRTRANSFORM_H + +#include "windowsmediaphoto.h" + +#define COMPUTE_CORNER_PRED_DIFF(a, b) (*(a) -= (b)) +#define COMPUTE_CORNER_PRED_ADD(a, b) (*(a) += (b)) + +/** 2x2 foward DCT == 2x2 inverse DCT **/ +Void strDCT2x2dn(PixelI *, PixelI *, PixelI *, PixelI *); +Void strDCT2x2up(PixelI *, PixelI *, PixelI *, PixelI *); +Void FOURBUTTERFLY_HARDCODED1(PixelI *p); + +/** 2x2 dct of a group of 4**/ +#define FOURBUTTERFLY(p, i00, i01, i02, i03, i10, i11, i12, i13,\ + i20, i21, i22, i23, i30, i31, i32, i33) \ + strDCT2x2dn(&p[i00], &p[i01], &p[i02], &p[i03]); \ + strDCT2x2dn(&p[i10], &p[i11], &p[i12], &p[i13]); \ + strDCT2x2dn(&p[i20], &p[i21], &p[i22], &p[i23]); \ + strDCT2x2dn(&p[i30], &p[i31], &p[i32], &p[i33]) + +#endif // WMI_STRTRANSFORM_H \ No newline at end of file diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.o new file mode 100644 index 0000000..0369fe4 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strTransform.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.c new file mode 100644 index 0000000..b2648e7 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.c @@ -0,0 +1,1251 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include "strcodec.h" +#include "perfTimer.h" + +#ifdef MEM_TRACE +#define TRACE_MALLOC 1 +#define TRACE_NEW 0 +#define TRACE_HEAP 0 +#include "memtrace.h" +#endif + +//================================================================ +// Quantization index tables +//================================================================ +const int blkOffset[16] = {0, 64, 16, 80, 128, 192, 144, 208, 32, 96, 48, 112, 160, 224, 176, 240}; +const int blkOffsetUV[4] = {0, 32, 16, 48}; +const int blkOffsetUV_422[8] = {0, 64, 16, 80, 32, 96, 48, 112}; + +const int dctIndex[3][16] = { /** permutation matrix tailored to the transform, nothing to do with ZZS **/ + {0,5,1,6, 10,12,8,14, 2,4,3,7, 9,13,11,15}, //AC 444 + {0,5,1,6, 10,12,8,14, 2,4,3,7, 9,13,11,15}, //AC 420 + {0,128,64,208, 32,240,48,224, 16,192,80,144, 112,176,96,160 }, //DC 444 +}; + +//================================================================ +// Color conversion index table +//================================================================ +const U8 idxCC[16][16] = +{ + {0x00, 0x01, 0x05, 0x04, 0x40, 0x41, 0x45, 0x44, 0x80, 0x81, 0x85, 0x84, 0xc0, 0xc1, 0xc5, 0xc4, }, + {0x02, 0x03, 0x07, 0x06, 0x42, 0x43, 0x47, 0x46, 0x82, 0x83, 0x87, 0x86, 0xc2, 0xc3, 0xc7, 0xc6, }, + {0x0a, 0x0b, 0x0f, 0x0e, 0x4a, 0x4b, 0x4f, 0x4e, 0x8a, 0x8b, 0x8f, 0x8e, 0xca, 0xcb, 0xcf, 0xce, }, + {0x08, 0x09, 0x0d, 0x0c, 0x48, 0x49, 0x4d, 0x4c, 0x88, 0x89, 0x8d, 0x8c, 0xc8, 0xc9, 0xcd, 0xcc, }, + + {0x10, 0x11, 0x15, 0x14, 0x50, 0x51, 0x55, 0x54, 0x90, 0x91, 0x95, 0x94, 0xd0, 0xd1, 0xd5, 0xd4, }, + {0x12, 0x13, 0x17, 0x16, 0x52, 0x53, 0x57, 0x56, 0x92, 0x93, 0x97, 0x96, 0xd2, 0xd3, 0xd7, 0xd6, }, + {0x1a, 0x1b, 0x1f, 0x1e, 0x5a, 0x5b, 0x5f, 0x5e, 0x9a, 0x9b, 0x9f, 0x9e, 0xda, 0xdb, 0xdf, 0xde, }, + {0x18, 0x19, 0x1d, 0x1c, 0x58, 0x59, 0x5d, 0x5c, 0x98, 0x99, 0x9d, 0x9c, 0xd8, 0xd9, 0xdd, 0xdc, }, + + {0x20, 0x21, 0x25, 0x24, 0x60, 0x61, 0x65, 0x64, 0xa0, 0xa1, 0xa5, 0xa4, 0xe0, 0xe1, 0xe5, 0xe4, }, + {0x22, 0x23, 0x27, 0x26, 0x62, 0x63, 0x67, 0x66, 0xa2, 0xa3, 0xa7, 0xa6, 0xe2, 0xe3, 0xe7, 0xe6, }, + {0x2a, 0x2b, 0x2f, 0x2e, 0x6a, 0x6b, 0x6f, 0x6e, 0xaa, 0xab, 0xaf, 0xae, 0xea, 0xeb, 0xef, 0xee, }, + {0x28, 0x29, 0x2d, 0x2c, 0x68, 0x69, 0x6d, 0x6c, 0xa8, 0xa9, 0xad, 0xac, 0xe8, 0xe9, 0xed, 0xec, }, + + {0x30, 0x31, 0x35, 0x34, 0x70, 0x71, 0x75, 0x74, 0xb0, 0xb1, 0xb5, 0xb4, 0xf0, 0xf1, 0xf5, 0xf4, }, + {0x32, 0x33, 0x37, 0x36, 0x72, 0x73, 0x77, 0x76, 0xb2, 0xb3, 0xb7, 0xb6, 0xf2, 0xf3, 0xf7, 0xf6, }, + {0x3a, 0x3b, 0x3f, 0x3e, 0x7a, 0x7b, 0x7f, 0x7e, 0xba, 0xbb, 0xbf, 0xbe, 0xfa, 0xfb, 0xff, 0xfe, }, + {0x38, 0x39, 0x3d, 0x3c, 0x78, 0x79, 0x7d, 0x7c, 0xb8, 0xb9, 0xbd, 0xbc, 0xf8, 0xf9, 0xfd, 0xfc, }, +}; + +const U8 idxCC_420[8][8] = +{ + {0x00, 0x01, 0x05, 0x04, 0x20, 0x21, 0x25, 0x24, }, + {0x02, 0x03, 0x07, 0x06, 0x22, 0x23, 0x27, 0x26, }, + {0x0a, 0x0b, 0x0f, 0x0e, 0x2a, 0x2b, 0x2f, 0x2e, }, + {0x08, 0x09, 0x0d, 0x0c, 0x28, 0x29, 0x2d, 0x2c, }, + + {0x10, 0x11, 0x15, 0x14, 0x30, 0x31, 0x35, 0x34, }, + {0x12, 0x13, 0x17, 0x16, 0x32, 0x33, 0x37, 0x36, }, + {0x1a, 0x1b, 0x1f, 0x1e, 0x3a, 0x3b, 0x3f, 0x3e, }, + {0x18, 0x19, 0x1d, 0x1c, 0x38, 0x39, 0x3d, 0x3c, }, +}; + +/************************************************************************* + gGDISignature +*************************************************************************/ +const Char gGDISignature[] = {'W', 'M', 'P', 'H', 'O', 'T', 'O', '\0'}; + +// check if enough memory allocated for the image buffer +Int checkImageBuffer(CWMImageStrCodec * pSC, size_t cWidth, size_t cRows) +{ + const BITDEPTH_BITS bd = pSC->WMISCP.bYUVData ? + BD_32S : pSC->WMII.bdBitDepth; + const COLORFORMAT cf = pSC->WMISCP.bYUVData ? + pSC->m_param.cfColorFormat : pSC->WMII.cfColorFormat; + size_t cBytes; + Bool bLessThan64Bit = sizeof(void *) < 8; + + if(cf == YUV_420) + cRows = (cRows + 1) / 2; + if(cRows > pSC->WMIBI.cLine) + return ICERR_ERROR; + + if(cf == YUV_422 || cf == YUV_420) + cWidth = (cWidth + 1) / 2; + + if (bLessThan64Bit && (cWidth >> ((sizeof(size_t) * 8 - 5)))) { + /** potential overflow - 32 bit pointers insufficient to address cache **/ + /** this uses 2 macroblock row constraint, which is tighter than ensuring rollover doesn't occur below **/ + return ICERR_ERROR; + } + + cBytes = pSC->WMISCP.bYUVData ? cWidth * sizeof(PixelI) * + (cf == YUV_420 ? 6 : (cf == YUV_422 ? 4 : (cf == YUV_444 ? 3 : 1))) : + (bd == BD_1 ? (pSC->WMII.cBitsPerUnit * cWidth + 7) / 8 : (pSC->WMII.cBitsPerUnit + 7) / 8 * cWidth); + + return (cBytes > pSC->WMIBI.cbStride ? ICERR_ERROR : ICERR_OK); +} + +Void writeQPIndex(BitIOInfo * pIO, U8 uiIndex, U32 cBits) +{ + if(uiIndex == 0) + putBit16(pIO, 1, 1); // default QP + else{ + putBit16(pIO, 0, 1); // non default QP + putBit16(pIO, uiIndex - 1, cBits); + } +} + +U8 readQPIndex(BitIOInfo * pIO, U32 cBits) +{ + if(getBit16(pIO, 1)) + return 0; // default QP + + return (U8) getBit16(pIO, cBits) + 1; +} + +Void getTilePos(CWMImageStrCodec* pSC, size_t mbX, size_t mbY) +{ + if(mbX == 0){ // left image boundary + pSC->cTileColumn = 0; + } + else if(pSC->cTileColumn < pSC->WMISCP.cNumOfSliceMinus1V && mbX == pSC->WMISCP.uiTileX[pSC->cTileColumn + 1]){ // left tile boundary + pSC->cTileColumn ++; + } + + if(mbY == 0){ // top image boundary + pSC->cTileRow = 0; + } + else if(pSC->cTileRow < pSC->WMISCP.cNumOfSliceMinus1H && mbY == pSC->WMISCP.uiTileY[pSC->cTileRow + 1]){ // top tile boundary + pSC->cTileRow ++; + } + + pSC->m_bCtxLeft = (mbX == pSC->WMISCP.uiTileX[pSC->cTileColumn]); + pSC->m_bCtxTop = (mbY == pSC->WMISCP.uiTileY[pSC->cTileRow]); + + pSC->m_bResetContext = pSC->m_bResetRGITotals = (((mbX - pSC->WMISCP.uiTileX[pSC->cTileColumn]) & 0xf) == 0); + if(pSC->cTileColumn == pSC->WMISCP.cNumOfSliceMinus1V){ // last tile column + if(mbX + 1 == pSC->cmbWidth) + pSC->m_bResetContext = TRUE; + } + else if(mbX + 1 == pSC->WMISCP.uiTileX[pSC->cTileColumn + 1]) + pSC->m_bResetContext = TRUE; +} + +//================================================================ +// utility functions for 2 macro block rows +//================================================================ +Void initMRPtr(CWMImageStrCodec* pSC) +{ + size_t j, jend = (pSC->m_pNextSC != NULL); + + for (j = 0; j <= jend; j++) { + memcpy (pSC->p0MBbuffer, pSC->a0MBbuffer, sizeof (pSC->p0MBbuffer)); + memcpy (pSC->p1MBbuffer, pSC->a1MBbuffer, sizeof (pSC->p1MBbuffer)); + pSC = pSC->m_pNextSC; + } +} + +Void advanceMRPtr(CWMImageStrCodec* pSC) +{ + const COLORFORMAT cf = pSC->m_param.cfColorFormat; + const int cpChroma = cblkChromas[cf] * 16; + size_t i, j, jend = (pSC->m_pNextSC != NULL); + + assert(pSC->m_bSecondary == FALSE); + for (j = 0; j <= jend; j++) { + int cpStride = 16 * 16; + for (i = 0; i < pSC->m_param.cNumChannels; i++) { + pSC->pPlane[i] = pSC->p0MBbuffer[i]; + + pSC->p0MBbuffer[i] += cpStride; + pSC->p1MBbuffer[i] += cpStride; + + cpStride = cpChroma; + } + pSC = pSC->m_pNextSC; + } +} + +/* advance to next MB row */ +Void advanceOneMBRow(CWMImageStrCodec *pSC) +{ + size_t i, j, jend = (pSC->m_pNextSC != NULL); + CWMIPredInfo *pPredInfo; + + for (j = 0; j <= jend; j++) { + for(i = 0; i < pSC->m_param.cNumChannels; i ++){ // swap current row and previous row + pPredInfo = pSC->PredInfo[i]; + pSC->PredInfo[i] = pSC->PredInfoPrevRow[i]; + pSC->PredInfoPrevRow[i] = pPredInfo; + } + pSC = pSC->m_pNextSC; + } +} + +Void swapMRPtr(CWMImageStrCodec* pSC) +{ + PixelI *pTemp[MAX_CHANNELS]; + size_t j, jend = (pSC->m_pNextSC != NULL); + + for (j = 0; j <= jend; j++) { + memcpy (pTemp, pSC->a0MBbuffer, sizeof (pSC->a0MBbuffer)); + memcpy (pSC->a0MBbuffer, pSC->a1MBbuffer, sizeof (pSC->a0MBbuffer)); + memcpy (pSC->a1MBbuffer, pTemp, sizeof (pSC->a0MBbuffer)); + pSC = pSC->m_pNextSC; + } +} + +//================================================================ +// Empty function to fill slot +//================================================================ +Int IDPEmpty(CWMImageStrCodec* pSC) +{ + UNREFERENCED_PARAMETER( pSC ); + + return ICERR_OK; +} + +ERR WMPAlloc(void** ppv, size_t cb) +{ + *ppv = calloc(1, cb); + return *ppv ? WMP_errSuccess : WMP_errOutOfMemory; +} + +ERR WMPFree(void** ppv) +{ + if (*ppv) + { + free(*ppv); + *ppv = NULL; + } + + return WMP_errSuccess; +} + +//================================================================ +// Streaming I/O functions +//================================================================ +ERR CreateWS_File(struct WMPStream** ppWS, const char* szFilename, const char* szMode) +{ + ERR err = WMP_errSuccess; + struct WMPStream* pWS = NULL; + + Call(WMPAlloc((void** )ppWS, sizeof(**ppWS))); + pWS = *ppWS; + + pWS->Close = CloseWS_File; + pWS->EOS = EOSWS_File; + + pWS->Read = ReadWS_File; + pWS->Write = WriteWS_File; + //pWS->GetLine = GetLineWS_File; + + pWS->SetPos = SetPosWS_File; + pWS->GetPos = GetPosWS_File; + +#ifdef _WIN32 + FailIf(0 != fopen_s(&pWS->state.file.pFile, szFilename, szMode), WMP_errFileIO); +#else + pWS->state.file.pFile = fopen(szFilename, szMode); + FailIf(NULL == pWS->state.file.pFile, WMP_errFileIO); +#endif + +Cleanup: + return err; +} + +ERR CloseWS_File(struct WMPStream** ppWS) +{ + ERR err = WMP_errSuccess; + struct WMPStream* pWS = *ppWS; + + fclose(pWS->state.file.pFile); + Call(WMPFree((void**)ppWS)); + +Cleanup: + return err; +} + +Bool EOSWS_File(struct WMPStream* pWS) +{ + return feof(pWS->state.file.pFile); +} + +ERR ReadWS_File(struct WMPStream* pWS, void* pv, size_t cb) +{ + // ERR err = WMP_errSuccess; + + return (fread(pv, cb, 1, pWS->state.file.pFile) == 1) ? WMP_errSuccess : WMP_errFileIO; +} + +ERR WriteWS_File(struct WMPStream* pWS, const void* pv, size_t cb) +{ + ERR err = WMP_errSuccess; + + if(0 != cb) + { + FailIf(1 != fwrite(pv, cb, 1, pWS->state.file.pFile), WMP_errFileIO); + } + +Cleanup: + return err; +} + +ERR SetPosWS_File(struct WMPStream* pWS, size_t offPos) +{ + ERR err = WMP_errSuccess; + + FailIf(0 != fseek(pWS->state.file.pFile, (long)offPos, SEEK_SET), WMP_errFileIO); + +Cleanup: + return err; +} + +ERR GetPosWS_File(struct WMPStream* pWS, size_t* poffPos) +{ + ERR err = WMP_errSuccess; + long lOff = 0; + + FailIf(-1 == (lOff = ftell(pWS->state.file.pFile)), WMP_errFileIO); + *poffPos = (size_t)lOff; + +Cleanup: + return err; +} + +//---------------------------------------------------------------- +ERR CreateWS_Memory(struct WMPStream** ppWS, void* pv, size_t cb) +{ + ERR err = WMP_errSuccess; + struct WMPStream* pWS = NULL; + + Call(WMPAlloc((void** )ppWS, sizeof(**ppWS))); + pWS = *ppWS; + + pWS->state.buf.pbBuf = pv; + pWS->state.buf.cbBuf = cb; + pWS->state.buf.cbCur = 0; + + pWS->Close = CloseWS_Memory; + pWS->EOS = EOSWS_Memory; + + pWS->Read = ReadWS_Memory; + pWS->Write = WriteWS_Memory; + + pWS->SetPos = SetPosWS_Memory; + pWS->GetPos = GetPosWS_Memory; + +Cleanup: + return err; +} + +ERR CloseWS_Memory(struct WMPStream** ppWS) +{ + ERR err = WMP_errSuccess; + + Call(WMPFree((void**)ppWS)); + +Cleanup: + return err; +} + +Bool EOSWS_Memory(struct WMPStream* pWS) +{ + return pWS->state.buf.cbBuf <= pWS->state.buf.cbCur; +} + +ERR ReadWS_Memory(struct WMPStream* pWS, void* pv, size_t cb) +{ + ERR err = WMP_errSuccess; + +// FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur, WMP_errBufferOverflow); + if(pWS->state.buf.cbBuf < pWS->state.buf.cbCur) + return err; + + FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow); + if (pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb) + { + cb = pWS->state.buf.cbBuf - pWS->state.buf.cbCur; + } + + memcpy(pv, pWS->state.buf.pbBuf + pWS->state.buf.cbCur, cb); + pWS->state.buf.cbCur += cb; + +Cleanup: + return err; +} + +ERR WriteWS_Memory(struct WMPStream* pWS, const void* pv, size_t cb) +{ + ERR err = WMP_errSuccess; + + FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow); + FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb, WMP_errBufferOverflow); + + memcpy(pWS->state.buf.pbBuf + pWS->state.buf.cbCur, pv, cb); + pWS->state.buf.cbCur += cb; + +Cleanup: + return err; +} + +ERR SetPosWS_Memory(struct WMPStream* pWS, size_t offPos) +{ + ERR err = WMP_errSuccess; + + //While the following condition is possibly useful, failure occurs + //at the end of a file since packets beyond the end may be accessed + //FailIf(pWS->state.buf.cbBuf < offPos, WMP_errBufferOverflow); + pWS->state.buf.cbCur = offPos; + +//Cleanup: + return err; +} + +ERR GetPosWS_Memory(struct WMPStream* pWS, size_t* poffPos) +{ + *poffPos = pWS->state.buf.cbCur; + + return WMP_errSuccess; +} + +//================================================================= +// Linked list based WMPStream +// - for indefinite size, multiple stream out +// - reads not supported in this mode +//================================================================= +ERR CreateWS_List(struct WMPStream** ppWS) +{ + ERR err = WMP_errSuccess; + struct WMPStream* pWS = NULL; + + Call(WMPAlloc((void** )ppWS, sizeof(**ppWS) + PACKETLENGTH + sizeof(void *))); + pWS = *ppWS; + + pWS->state.buf.pbBuf = (U8 *)pWS + sizeof(**ppWS) + sizeof(void *); // first buffer points here + + memset(pWS->state.buf.pbBuf - sizeof(void *), 0, sizeof(void *)); + pWS->state.buf.cbBuf = PACKETLENGTH; + pWS->state.buf.cbCur = 0; + pWS->state.buf.cbBufCount = 0; + + pWS->Close = CloseWS_List; + pWS->EOS = NULL; // doesn't get called + + pWS->Read = ReadWS_List; + pWS->Write = WriteWS_List; + + pWS->SetPos = SetPosWS_List; + pWS->GetPos = GetPosWS_List; + + //printf ("create buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf); + +Cleanup: + return err; +} + +ERR CloseWS_List(struct WMPStream** ppWS) +{ + ERR err = WMP_errSuccess; + + if (ppWS) { + U8 *pBuf = (U8 *)(ppWS[0] + 1); // pointer to buffer + U8 *pNext = (U8 *)(((void **)pBuf)[0]); + while (pNext) { +//struct WMPStream *pWS = ppWS[0]; + pBuf = pNext; + pNext = (U8 *)(((void **)(pBuf))[0]); +//printf ("delete buffer %x\n", pBuf); + Call(WMPFree((void**)&pBuf)); + } + } + Call(WMPFree((void**)ppWS)); + +Cleanup: + return err; +} + +ERR ReadWS_List(struct WMPStream* pWS, void* pv, size_t cb) +{ + ERR err = WMP_errSuccess; + + FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow); + if (pWS->state.buf.cbBuf < pWS->state.buf.cbCur + PACKETLENGTH * pWS->state.buf.cbBufCount + cb) + { + cb = pWS->state.buf.cbBuf - pWS->state.buf.cbCur - PACKETLENGTH * pWS->state.buf.cbBufCount; + } + + while (cb) { + size_t cl = PACKETLENGTH - pWS->state.buf.cbCur; + if (cl > cb) + cl = cb; + memcpy(pv, pWS->state.buf.pbBuf + pWS->state.buf.cbCur, cl); + pWS->state.buf.cbCur += cl; + pv = (void *)((U8 *)pv + cl); + cb -= cl; + if (pWS->state.buf.cbCur == PACKETLENGTH) { + pWS->state.buf.pbBuf = (U8 *)((void **)(pWS->state.buf.pbBuf - sizeof(void *)))[0] + sizeof(void *); + pWS->state.buf.cbCur = 0; + pWS->state.buf.cbBufCount++; + + //printf ("read buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf); + } + } + +Cleanup: + return err; +} + +ERR WriteWS_List(struct WMPStream* pWS, const void* pv, size_t cb) +{ + ERR err = WMP_errSuccess; + + FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow); + FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb, WMP_errBufferOverflow); + + while (cb) { + size_t cl = PACKETLENGTH - pWS->state.buf.cbCur; + if (cl > cb) + cl = cb; + memcpy(pWS->state.buf.pbBuf + pWS->state.buf.cbCur, pv, cl); + pWS->state.buf.cbCur += cl; + pv = (const void *)((U8 *)pv + cl); + cb -= cl; + if (pWS->state.buf.cbCur == PACKETLENGTH) { // allocate next packet in list + U8 *pBuf = NULL; + void **pPtrLoc = (void **)(pWS->state.buf.pbBuf - sizeof(void *)); + Call(WMPAlloc((void **)&pBuf, PACKETLENGTH + sizeof(void *))); + pPtrLoc[0] = (void *)pBuf; + pWS->state.buf.pbBuf = pBuf + sizeof(void *); + pWS->state.buf.cbBuf += PACKETLENGTH; + memset(pBuf, 0, sizeof(void *)); + pWS->state.buf.cbCur = 0; + pWS->state.buf.cbBufCount++; + + //printf ("create buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf); + } + } + +Cleanup: + return err; +} + +ERR SetPosWS_List(struct WMPStream* pWS, size_t offPos) +{ + ERR err = WMP_errSuccess; + + // get the first buffer + U8 *pBuf = (U8 *)(pWS + 1); // pointer to buffer + pWS->state.buf.cbCur = 0; + pWS->state.buf.cbBufCount = 0; + + while (offPos >= PACKETLENGTH && pBuf != NULL) { + pBuf = (U8 *)(((void **)pBuf)[0]); + offPos -= PACKETLENGTH; + pWS->state.buf.cbBufCount++; + } + + if (pBuf == NULL) + goto Cleanup; + + pWS->state.buf.cbCur = offPos; + pWS->state.buf.pbBuf = pBuf + sizeof(void *); + //printf ("seek buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf); + +Cleanup: + return err; +} + +ERR GetPosWS_List(struct WMPStream* pWS, size_t* poffPos) +{ + *poffPos = pWS->state.buf.cbCur + PACKETLENGTH * pWS->state.buf.cbBufCount; + + return WMP_errSuccess; +} + +//================================================================ +// Simple BitIO access functions +//================================================================ +// init SimpleBitIO +ERR attach_SB(SimpleBitIO* pSB, struct WMPStream* pWS) +{ + pSB->pWS = pWS; + pSB->cbRead = 0; + pSB->bAccumulator = 0; + pSB->cBitLeft = 0; + + return WMP_errSuccess; +} + +// extract upto 32bit from input stream +U32 getBit32_SB(SimpleBitIO* pSB, U32 cBits) +{ + U32 rc = 0; + + while (pSB->cBitLeft < cBits) + { + rc <<= pSB->cBitLeft; + rc |= pSB->bAccumulator >> (8 - pSB->cBitLeft); + + cBits -= pSB->cBitLeft; + + pSB->pWS->Read(pSB->pWS, &pSB->bAccumulator, 1); + pSB->cbRead++; + pSB->cBitLeft = 8; + } + + rc <<= cBits; + rc |= pSB->bAccumulator >> (8 - cBits); + pSB->bAccumulator <<= cBits; + pSB->cBitLeft -= cBits; + + return rc; +} + +// ignore input to byte boundary +Void flushToByte_SB(SimpleBitIO* pSB) +{ + pSB->bAccumulator = 0; + pSB->cBitLeft = 0; +} + +// return read byte count +U32 getByteRead_SB(SimpleBitIO* pSB) +{ + return pSB->cbRead; +} + +ERR detach_SB(SimpleBitIO* pSB) +{ + assert(0 == pSB->cBitLeft); + pSB->pWS = NULL; + + return WMP_errSuccess; +} + +//================================================================ +// Memory access functions +//================================================================ +#if (defined(_WIN32) && !defined(UNDER_CE)) || (defined(UNDER_CE) && defined(_ARM_)) +// WinCE ARM and Desktop x86 +#else +// other platform +#ifdef _BIG__ENDIAN_ +#define _byteswap_ulong(x) (x) +#else // _BIG__ENDIAN_ +U32 _byteswap_ulong(U32 bits) +{ + U32 r = (bits & 0xffu) << 24; + r |= (bits << 8) & 0xff0000u; + r |= ((bits >> 8) & 0xff00u); + r |= ((bits >> 24) & 0xffu); + + return r; +} +#endif // _BIG__ENDIAN_ +#endif + +U32 load4BE(void* pv) +{ +#ifdef _BIG__ENDIAN_ + return (*(U32*)pv); +#else // _BIG__ENDIAN_ +#if defined(_M_IA64) || defined(_ARM_) + U32 v; + v = ((U16 *) pv)[0]; + v |= ((U32)((U16 *) pv)[1]) << 16; + return _byteswap_ulong(v); +#else // _M_IA64 + return _byteswap_ulong(*(U32*)pv); +#endif // _M_IA64 +#endif // _BIG__ENDIAN_ +} + +#define LOAD16 load4BE + +#ifdef _BIG__ENDIAN_ +#define WRITESWAP_ENDIAN(a) ((a)>>16) +#else // _BIG__ENDIAN_ +#define WRITESWAP_ENDIAN(a) _byteswap_ulong(a) +#endif // _BIG__ENDIAN_ + +//================================================================ +// Bit I/O functions +//================================================================ +Int allocateBitIOInfo(CWMImageStrCodec* pSC) +{ + U32 cNumBitIO; + SUBBAND sbSubband = pSC->WMISCP.sbSubband; + + pSC->cSB = (sbSubband == SB_DC_ONLY ? 1 : (sbSubband == SB_NO_HIGHPASS ? 2 : (sbSubband == SB_NO_FLEXBITS ? 3 : 4))); + + // # of additional BitIOs other than pSC->pIOHeader + if (!pSC->m_param.bIndexTable) { // pure streaming mode, no index table, no additional BitIO! + assert (pSC->WMISCP.bfBitstreamFormat == SPATIAL && pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V == 0); + cNumBitIO = 0; + } + else if(pSC->WMISCP.bfBitstreamFormat == SPATIAL) + cNumBitIO = pSC->WMISCP.cNumOfSliceMinus1V + 1; + else + cNumBitIO = (pSC->WMISCP.cNumOfSliceMinus1V + 1) * pSC->cSB; + + if(cNumBitIO > MAX_TILES * 4) + return ICERR_ERROR; + + // allocate additional BitIos + if(cNumBitIO > 0){ + U32 i = 0; + size_t cb = sizeof(BitIOInfo) * cNumBitIO + (PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 * cNumBitIO; + U8* pb = (U8*)malloc(cb); + + if (NULL == pb) return ICERR_ERROR; + memset(pb, 0, cb); + + pSC->m_ppBitIO = (BitIOInfo**)pb; + pb += sizeof(BitIOInfo) * cNumBitIO; + + pb = (U8*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2; + for (i = 0; i < cNumBitIO; ++i){ + pSC->m_ppBitIO[i] = (BitIOInfo*)pb; + pb += PACKETLENGTH * 4; + } + + // allocate index table + if(cNumBitIO > MAX_TILES * 4 || pSC->WMISCP.cNumOfSliceMinus1H >= MAX_TILES) + return ICERR_ERROR; + pSC->pIndexTable = malloc(cNumBitIO * (pSC->WMISCP.cNumOfSliceMinus1H + 1) * sizeof(size_t)); + if(NULL == pSC->pIndexTable) return ICERR_ERROR; + } + + pSC->cNumBitIO = cNumBitIO; + + return ICERR_OK; +} + +Int setBitIOPointers(CWMImageStrCodec* pSC) +{ + if(pSC->cNumBitIO > 0){ + U32 i; + + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){ + CCodingContext * pContext = &pSC->m_pCodingContext[i]; + if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){ + pContext->m_pIODC = pContext->m_pIOLP = pContext->m_pIOAC = pContext->m_pIOFL = pSC->m_ppBitIO[i]; + } + else{ + U32 j = pSC->cSB; + + pContext->m_pIODC = pSC->m_ppBitIO[i * j]; + if(j > 1) + pContext->m_pIOLP = pSC->m_ppBitIO[i * j + 1]; + if(j > 2) + pContext->m_pIOAC = pSC->m_ppBitIO[i * j + 2]; + if(j > 3) + pContext->m_pIOFL = pSC->m_ppBitIO[i * j + 3]; + } + } + } + else{ // streamimg mode + CCodingContext * pContext = &pSC->m_pCodingContext[0]; + pContext->m_pIODC = pContext->m_pIOLP = pContext->m_pIOAC = pContext->m_pIOFL = pSC->pIOHeader; + } + + return ICERR_OK; +} + +Int allocateTileInfo(CWMImageStrCodec * pSC) +{ + size_t i; + + if(pSC->WMISCP.cNumOfSliceMinus1V >= MAX_TILES) + return ICERR_ERROR; + pSC->pTile = (CWMITile *)malloc((pSC->WMISCP.cNumOfSliceMinus1V + 1) * sizeof(CWMITile)); + if(pSC->pTile == NULL) + return ICERR_ERROR; + memset(pSC->pTile, 0, (pSC->WMISCP.cNumOfSliceMinus1V + 1) * sizeof(CWMITile)); + + for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++) + pSC->pTile[i].cNumQPHP = pSC->pTile[i].cNumQPLP = 1, pSC->pTile[i].cBitsHP = pSC->pTile[i].cBitsLP = 0; + + return ICERR_OK; +} + +Void freeTileInfo(CWMImageStrCodec * pSC) +{ + size_t iTile; + + if((pSC->m_param.uQPMode & 1) != 0) // not DC uniform + for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++) + freeQuantizer(pSC->pTile[iTile].pQuantizerDC); + else + freeQuantizer(pSC->pTile[0].pQuantizerDC); + + if(pSC->WMISCP.sbSubband != SB_DC_ONLY) + if((pSC->m_param.uQPMode & 2) != 0) // not LP uniform + for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++) + freeQuantizer(pSC->pTile[iTile].pQuantizerLP); + else + freeQuantizer(pSC->pTile[0].pQuantizerLP); + + if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS) + if((pSC->m_param.uQPMode & 4) != 0) // not HP uniform + for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++) + freeQuantizer(pSC->pTile[iTile].pQuantizerHP); + else + freeQuantizer(pSC->pTile[0].pQuantizerHP); + + if(pSC->pTile != NULL) + free(pSC->pTile); +} + +Int allocateQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], size_t cChannel, size_t cQP) +{ + size_t iCh; + + if(cQP > 16 || cChannel > MAX_CHANNELS) + return ICERR_ERROR; + pQuantizer[0] = (CWMIQuantizer *)malloc(cQP * sizeof(CWMIQuantizer) * cChannel); + if(pQuantizer[0] == NULL) + return ICERR_ERROR; + + for(iCh = 1; iCh < cChannel; iCh ++) + pQuantizer[iCh] = pQuantizer[iCh - 1] + cQP; + + return ICERR_OK; +} + +Void freeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS]) +{ + if(pQuantizer[0] != NULL) + free(pQuantizer[0]); +} + +Void formatQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], U8 cChMode, size_t cCh, size_t iPos, Bool bShiftedUV, + Bool bScaledArith) +{ + size_t iCh; + + for(iCh = 0; iCh < cCh; iCh ++){ + if(iCh > 0) + if(cChMode == 0) // uniform + pQuantizer[iCh][iPos] = pQuantizer[0][iPos]; + else if(cChMode == 1) // mixed + pQuantizer[iCh][iPos] = pQuantizer[1][iPos]; + remapQP(pQuantizer[iCh] + iPos, (iCh > 0 && bShiftedUV == TRUE) ? SHIFTZERO - 1 : SHIFTZERO, bScaledArith); + } +} + +Void setUniformQuantizer(CWMImageStrCodec * pSC, size_t sb) +{ + size_t iCh, iTile; + + for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++) + for(iTile = 1; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++) + if(sb == 0) // DC + pSC->pTile[iTile].pQuantizerDC[iCh] = pSC->pTile[0].pQuantizerDC[iCh]; + else if(sb == 1) // LP + pSC->pTile[iTile].pQuantizerLP[iCh] = pSC->pTile[0].pQuantizerLP[iCh]; + else // HP + pSC->pTile[iTile].pQuantizerHP[iCh] = pSC->pTile[0].pQuantizerHP[iCh]; +} + +Void useDCQuantizer(CWMImageStrCodec * pSC, size_t iTile) +{ + size_t iCh; + + for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++) + pSC->pTile[iTile].pQuantizerLP[iCh][0] = *pSC->pTile[iTile].pQuantizerDC[iCh]; +} + +Void useLPQuantizer(CWMImageStrCodec * pSC, size_t cQP, size_t iTile) +{ + size_t iCh, iQP; + + for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++) + for(iQP = 0; iQP < cQP; iQP ++) + pSC->pTile[iTile].pQuantizerHP[iCh][iQP] = pSC->pTile[iTile].pQuantizerLP[iCh][iQP]; +} + +U8 dquantBits(U8 cQP) +{ + return (cQP < 2 ? 0 : (cQP < 4 ? 1 : (cQP < 6 ? 2 : (cQP < 10 ? 3 : 4)))); +} + +#ifndef ARMOPT_BITIO +U32 peekBit16(BitIOInfo* pIO, U32 cBits) +{ + PEEKBIT16(pIO, cBits); +} + +U32 flushBit16(BitIOInfo* pIO, U32 cBits) +{ + FLUSHBIT16(pIO, cBits); +} + +U32 getBit16(BitIOInfo* pIO, U32 cBits) +{ + U32 uiRet = peekBit16(pIO, cBits); + flushBit16(pIO, cBits); + + return uiRet; +} + +U32 getBool16(BitIOInfo* pIO) +{ + U32 uiRet = peekBit16(pIO, 1); + flushBit16(pIO, 1); + return uiRet; +} + +/** this function returns cBits if zero is read, or a signed value if first cBits are not all zero **/ +I32 getBit16s(BitIOInfo* pIO, U32 cBits) +{ + U32 uiRet = peekBit16(pIO, cBits + 1); + if (uiRet < 2) { + flushBit16(pIO, cBits); + return 0; + } + else { + flushBit16(pIO, cBits + 1); + if (uiRet & 1) + return (-(I32)(uiRet >> 1)); + else + return (I32)(uiRet >> 1); + } +} + +U32 getBit32(BitIOInfo* pIO, U32 cBits) +{ + U32 uiRet = 0; + + assert(0 <= (I32)cBits && cBits <= 32); + + if (16 < cBits) + { + uiRet = getBit16(pIO, 16); + cBits -= 16; + uiRet <<= cBits; + } + + uiRet |= getBit16(pIO, cBits); + + return uiRet; +} + +U32 flushToByte(BitIOInfo* pIO) +{ + return flushBit16(pIO, (16 - pIO->cBitsUsed) & 7); +} +#endif // ARMOPT_BITIO + +//---------------------------------------------------------------- +Void putBit16z(BitIOInfo* pIO, U32 uiBits, U32 cBits) +{ + assert(cBits <= 16); + assert(0 == uiBits >> cBits); + + pIO->uiAccumulator = (pIO->uiAccumulator << cBits) | uiBits; + pIO->cBitsUsed += cBits; + + *(U16*)pIO->pbCurrent = (U16)WRITESWAP_ENDIAN(pIO->uiAccumulator << (32 - pIO->cBitsUsed)); + + pIO->pbCurrent = MASKPTR(pIO->pbCurrent + ((pIO->cBitsUsed >> 3) & 2), pIO->iMask); + pIO->cBitsUsed &= 16 - 1; +} + +Void putBit16(BitIOInfo* pIO, U32 uiBits, U32 cBits) +{ + assert(cBits <= 16); + + uiBits &= ~(-1 << cBits); + putBit16z(pIO, uiBits, cBits); +} + +Void putBit32(BitIOInfo* pIO, U32 uiBits, U32 cBits) +{ + assert(0 <= (I32)cBits && cBits <= 32); + + if (16 < cBits) + { + putBit16(pIO, uiBits >> (cBits - 16), 16); + cBits -= 16; + } + + putBit16(pIO, uiBits, cBits); +} + +Void fillToByte(BitIOInfo* pIO) +{ + putBit16z(pIO, 0, (16 - pIO->cBitsUsed) & 7); +} + +//---------------------------------------------------------------- +U32 getBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 cBits) +{ + U32 rc = getBit16(pIO, cBits); + readIS_L1(pSC, pIO); + + return rc; +} + +U32 putBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 uiBits, U32 cBits) +{ + putBit16(pIO, uiBits, cBits); + writeIS_L1(pSC, pIO); + + return 0; +} + + +//---------------------------------------------------------------- +// Query buffered data size held in BitIOInfo +// Write() for Enc, Read() for Dec +//---------------------------------------------------------------- +U32 getSizeRead(BitIOInfo* pIO) +{ + return (U32)(UINTPTR_T)(pIO->pbStart + PACKETLENGTH * 2 - pIO->pbCurrent) - pIO->cBitsUsed / 8; +} + +U32 getSizeWrite(BitIOInfo* pIO) +{ + return (U32)(UINTPTR_T)(pIO->pbCurrent + (pIO->pbStart <= pIO->pbCurrent ? 0 : PACKETLENGTH * 2) - pIO->pbStart) + pIO->cBitsUsed / 8; +} + +//---------------------------------------------------------------- +// Query stream offset from attached BitIO object for dec +//---------------------------------------------------------------- +U32 getPosRead(BitIOInfo* pIO) +{ + size_t cbCached = (pIO->pbStart + PACKETLENGTH * 2 - pIO->pbCurrent) - pIO->cBitsUsed / 8; + return (U32)(pIO->offRef - cbCached); +} + +//================================================================ +// Block I/O functions +//================================================================ +#ifndef ARMOPT_BITIO +ERR attachISRead(BitIOInfo* pIO, struct WMPStream* pWS, CWMImageStrCodec* pSC) +{ + UNREFERENCED_PARAMETER( pSC ); + + pWS->GetPos(pWS, &pIO->offRef); + + pIO->pbStart = (U8*)pIO - PACKETLENGTH * 2; + pIO->pbCurrent = pIO->pbStart; + + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + pWS->SetPos(pWS, pIO->offRef); + pWS->Read(pWS, pIO->pbStart, PACKETLENGTH * 2); + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + pIO->offRef += PACKETLENGTH * 2; + + pIO->uiAccumulator = load4BE(pIO->pbStart); + + pIO->cBitsUsed = 0; + pIO->iMask = ~(PACKETLENGTH * 2); + pIO->iMask &= ~1; + + pIO->pWS = pWS; + return WMP_errSuccess; +} + +ERR readIS(CWMImageStrCodec* pSC, BitIOInfo* pIO) +{ + ERR err = WMP_errSuccess; + + UNREFERENCED_PARAMETER( pSC ); + + if (PACKET1(pIO->pbStart, pIO->pbCurrent, PACKETLENGTH)) + { + struct WMPStream *pWS = pIO->pWS; + + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + //Call(0 != pIO->pWS->Read(pIO->pWS, pIO->pbStart, PACKETLENGTH)); + // TODO: add error checking code + pWS->SetPos(pWS, pIO->offRef); + pWS->Read(pWS, pIO->pbStart, PACKETLENGTH); + pIO->offRef += PACKETLENGTH; + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + + // make shadow copy for first 4B + pIO->uiShadow = *(U32*)pIO->pbStart; + + // reposition pbPacket pointer + pIO->pbStart = MASKPTR(pIO->pbStart + PACKETLENGTH, pIO->iMask); + } + +//Cleanup: + return err; +} + +ERR detachISRead(CWMImageStrCodec* pSC, BitIOInfo* pIO) +{ + ERR err = WMP_errSuccess; + + struct WMPStream* pWS = pIO->pWS; + size_t cbRemain = 0; + + // we can ONLY detach IStream at byte boundary + flushToByte(pIO); + assert(0 == (pIO->cBitsUsed % 8)); + Call(readIS_L1(pSC, pIO)); + + // set stream to right offset, undo buffering + cbRemain = (pIO->pbStart + PACKETLENGTH * 2) - (pIO->pbCurrent + pIO->cBitsUsed / 8); + pWS->SetPos(pWS, pIO->offRef - cbRemain); + + pIO->pWS = NULL; +Cleanup: + return err; +} +#endif // ARMOPT_BITIO + +//---------------------------------------------------------------- +ERR attachISWrite(BitIOInfo* pIO, struct WMPStream* pWS) +{ + pWS->GetPos(pWS, &pIO->offRef); + + pIO->pbStart = (U8*)pIO - PACKETLENGTH * 2; + pIO->pbCurrent = pIO->pbStart; + + pIO->uiAccumulator = 0; + pIO->cBitsUsed = 0; + pIO->iMask = ~(PACKETLENGTH * 2); + + pIO->pWS = pWS; + return WMP_errSuccess; +} + +// write out packet if we have >=1 packet data filled +ERR writeIS(CWMImageStrCodec* pSC, BitIOInfo* pIO) +{ + ERR err = WMP_errSuccess; + + UNREFERENCED_PARAMETER( pSC ); + + if (PACKET1(pIO->pbStart, pIO->pbCurrent, PACKETLENGTH)) + { + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + err = pIO->pWS->Write(pIO->pWS, pIO->pbStart, PACKETLENGTH); + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + Call(err); + + // reposition pbStart pointer + pIO->pbStart = MASKPTR(pIO->pbStart + PACKETLENGTH, pIO->iMask); + } + +Cleanup: + return err; +} + +// write out partially filled buffer and detach bitIO from IStream +ERR detachISWrite(CWMImageStrCodec* pSC, BitIOInfo* pIO) +{ + ERR err = WMP_errSuccess; + + // we can ONLY detach IStream at byte boundary + assert(0 == (pIO->cBitsUsed % 8)); + Call(writeIS_L1(pSC, pIO)); + + PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + err = pIO->pWS->Write(pIO->pWS, pIO->pbStart, pIO->pbCurrent + pIO->cBitsUsed / 8 - pIO->pbStart); + PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf); + Call(err); + + pIO->pWS = NULL; +Cleanup: + return err; +} + +//========================= +// Performance Measurement +//========================= +#ifndef DISABLE_PERF_MEASUREMENT + +void OutputIndivPerfTimer(struct PERFTIMERSTATE *pPerfTimer, + char *pszTimerName, + char *pszDescription, + float fltMegaPixels) +{ + PERFTIMERRESULTS rResults; + Bool fResult; + + fResult = FALSE; + printf("%s (%s): ", pszTimerName, pszDescription); + if (pPerfTimer) + { + fResult = PerfTimerGetResults(pPerfTimer, &rResults); + if (fResult) + { + printf("%.3f milliseconds, %.6f MP/sec\n", (float)rResults.iElapsedTime / 1000000, + 1000000000 * fltMegaPixels / rResults.iElapsedTime); + if (rResults.iZeroTimeIntervals > 0) + { + printf(" *** WARNING: %d time intervals were measured as zero. " + "This perf timer has insufficient precision!\n\n", + (int) rResults.iZeroTimeIntervals); + } + } + } + if (FALSE == fResult) + printf("Results not available!\n"); +} + + +void OutputPerfTimerReport(CWMImageStrCodec *pState) +{ + float fltMegaPixels; + + assert(pState->m_fMeasurePerf); + + printf("***************************************************************************\n"); + printf("* Perf Report\n"); + printf("***************************************************************************\n\n"); + + fltMegaPixels = (float)pState->WMII.cWidth * pState->WMII.cHeight / 1000000; + printf("Image Width = %d, Height = %d, total MegaPixels = %.1f MP\n", + (int) pState->WMII.cWidth, (int) pState->WMII.cHeight, fltMegaPixels); + + OutputIndivPerfTimer(pState->m_ptEncDecPerf, "m_ptEncDecPerf", "excl I/O", fltMegaPixels); + OutputIndivPerfTimer(pState->m_ptEndToEndPerf, "m_ptEndToEndPerf", "incl I/O", fltMegaPixels); +} + +#endif // DISABLE_PERF_MEASUREMENT diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.h new file mode 100644 index 0000000..b46e030 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.h @@ -0,0 +1,689 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#pragma once + +#include + +#include "windowsmediaphoto.h" +#include "common.h" +// #include "xplatform_image.h" + +// added for Xcode PK universal binary +#ifdef __ppc__ +#define _BIG__ENDIAN_ +#endif + +//================================================================ +#ifdef ENABLE_OPTIMIZATIONS +#if defined(_WIN32) && !defined(_WIN64) +#define WMP_OPT_SSE2 + +#define WMP_OPT_CC_ENC +//#define WMP_OPT_TRFM_ENC +//#define WMP_OPT_QT + +#define WMP_OPT_CC_DEC +#define WMP_OPT_TRFM_DEC + +#define X86OPT_INLINE + +#endif +#endif // ENABLE_OPTIMIZATIONS + +//================================================================ +//#ifdef _WIN32 +#if defined(_WIN32) && !defined(UNDER_CE) // _WIN32 seems to be defined always in VS2005 for ARM platform +#define PLATFORM_X86 +#include "..\x86\x86.h" +#endif + +#ifndef UNREFERENCED_PARAMETER +#define UNREFERENCED_PARAMETER(P) { (P) = (P); } +#endif UNREFERENCED_PARAMETER + +#ifdef UNDER_CE +#define PLATFORM_WCE +#include "arm.h" +#endif + +#ifdef __ANSI__ +#define PLATFORM_ANSI +#include "ansi.h" +#endif + +//================================================================ + +#ifdef PLATFORM_ANSI +typedef unsigned long long U64; +#else // PLATFORM_ANSI +typedef unsigned __int64 U64; +#endif // PLATFORM_ANSI + +//================================================================ +#define MARKERCOUNT (PACKETLENGTH * 2) + +// The following macros depend on UINTPTR_T and INTPTR_T being properly defined +// so that they are equal to pointer width. Confirm and fail if our assumptions are wrong. +CT_ASSERT(sizeof(UINTPTR_T) == sizeof(void*), strcodec1); +CT_ASSERT(sizeof(INTPTR_T) == sizeof(void*), strcodec2); + +// wrap around pointer, s=pow(2,n), p wraps aligned to s +#define WRAPPTR(p, s) ((void*)((UINTPTR_T)(p) & ~(UINTPTR_T)(s))) + +// mask certain bit inside a pointer, simulate wrap around +#define MASKPTR(p, m) ((void*)((UINTPTR_T)(p) & (INTPTR_T)(m))) + +// test for more than 1 packet data +#define PACKET1(ps, pc, s) (((INTPTR_T)(ps) ^ (INTPTR_T)(pc)) & ((UINTPTR_T)(s))) + +// alternate pointer p between 2 values aligned to s, s=pow(2,n) +//#define ALTPTR(p, s) ((void*)((uintptr_t)(p) ^ (s))) + +// align point, s=pow(2,n), p aligns to s +#define ALIGNUP(p, s) ((void*)(((UINTPTR_T)(p) + ((UINTPTR_T)(s) - 1)) & ~((UINTPTR_T)(s) - 1))) +#define ALIGNDOWN(p, s) ((void*)((UINTPTR_T)(p) & ~((UINTPTR_T)(s) - 1))) + +//================================================================ +// timer support +//================================================================ + +#define TraceResult(a) + +//================================================================ +typedef enum tagPacketType +{ + PK_NULL = 0, + PK_DC = 1, PK_AD, PK_AC, PK_CP, + PK_MAX, +} PACKETTYPE; + +typedef struct tagIOContext +{ + U8 P0[PACKETLENGTH]; // packet circular buffer 0 + U8 P1[PACKETLENGTH]; // packet circular buffer 1 + + union + { + U8 P2[PACKETLENGTH]; + struct + { + U32 uiShadow; // shadow of P0[0]-P0[3] + + U32 uiAccumulator; // 32bit acc as bit field cache + U32 cBitsUsed; // # of bits used of acc, [0,16) + + U8* pbPacket; // packet pointer + U8* pbCurrent; // current pointer + + struct WMPStream* pWS; // pointer to WMPStream + long offPacket; // byte offset into stream + + //ULARGE_INTEGER u64Acc; + + //======================================== + // index packet, used for packet retrieval + //======================================== + U32 cIndex; // current index for index packet + long offIndex; // byte offset into stream for index packet + }State; + }P2Info; + U8 P3[PACKETLENGTH]; // index packet buffer +} IOContext; + +typedef struct tagMemReadState +{ + U8* pbBuf; + size_t cbBuf; + size_t cbCur; +} MemReadState; + +typedef struct tagBitIOInfo +{ + U32 uiShadow; // shadow of first 4B of circular buffer + + U32 uiAccumulator; // 32bit acc as bit field cache + U32 cBitsUsed; // # of bits used of acc, [0,16) +#ifdef ARMOPT_BITIO + U32 cBitsUnused; // # of bits remain unused in acc, [0,32] +#endif + + I32 iMask; // mask used simulate pointer wrap around + + U8* pbStart; // start pointer +#ifndef ARMOPT_BITIO + U8* pbCurrent; // current pointer +#else + U32* pbCurrent; // current pointer +#endif + + struct WMPStream* pWS; // pointer to WMPStream + size_t offRef; // reference offset on IStream, + // for read, it moves along the stream + // for write, it stays at the attach point +} BitIOInfo; + +//================================================================ +typedef struct tagCWMIQuantizer { + U8 iIndex; + I32 iQP; + I32 iOffset; + I32 iMan; + I32 iExp; +#if defined(WMP_OPT_QT) + float f1_QP; + double d1_QP; +#endif +} CWMIQuantizer; + +/* temporary bridge between old APIs and streaming APIs */ +typedef struct tagCWMIMBInfo { + I32 iBlockDC[MAX_CHANNELS][16]; + I32 iOrientation; + Int iCBP[MAX_CHANNELS]; + Int iDiffCBP[MAX_CHANNELS]; + U8 iQIndexLP; // 0 - 15 + U8 iQIndexHP; // 0 - 15 +} CWMIMBInfo; + +struct CWMImageStrCodec; + +typedef Int (*ImageDataProc)(struct CWMImageStrCodec*); + +/** scan model **/ +typedef struct CAdaptiveScan { + U32 uTotal; + U32 uScan; +} CAdaptiveScan; + +/** Adaptive context model **/ +typedef struct CCodingContext { + BitIOInfo * m_pIODC; + BitIOInfo * m_pIOLP; + BitIOInfo * m_pIOAC; + BitIOInfo * m_pIOFL; + + /** adaptive huffman structs **/ + CAdaptiveHuffman *m_pAdaptHuffCBPCY; + CAdaptiveHuffman *m_pAdaptHuffCBPCY1; + CAdaptiveHuffman *m_pAHexpt[NUMVLCTABLES]; + + /** 4x4 zigzag patterns */ + CAdaptiveScan m_aScanLowpass[16]; + CAdaptiveScan m_aScanHoriz[16]; + CAdaptiveScan m_aScanVert[16]; + + /** Adaptive bit reduction model **/ + CAdaptiveModel m_aModelAC; + CAdaptiveModel m_aModelLP; + CAdaptiveModel m_aModelDC; + + /** Adaptive lowpass CBP model **/ + Int m_iCBPCountZero; + Int m_iCBPCountMax; + + /** Adaptive AC CBP model **/ + CCBPModel m_aCBPModel; + + /** Trim flex bits - externally set **/ + Int m_iTrimFlexBits; + + Bool m_bInROI; // inside ROI (for region decode and compressed domain cropping)? +} CCodingContext; + +// Following stuff used to be in strPredQuant.h +/* circulant buffer for 2 MB rows: current row and previous row */ +typedef struct tagCWMIPredInfo { + Int iQPIndex; // QP Index + Int iCBP; // coded block pattern + PixelI iDC; // DC of MB + PixelI iAD[6]; + PixelI * piAD; // AC of DC block: [2] 420UV [4] 422UV [6] elsewhere +}CWMIPredInfo; + +// the following is used on decode side while reading image info +typedef struct CWMImageStrCodecParameters { + size_t cVersion; + size_t cSubVersion; + COLORFORMAT cfColorFormat; // color format + Bool bRBSwapped; // blue and red shall be swapped in BGR555,565,101010 + Bool bAlphaChannel; // alpha channel present + Bool bScaledArith; // lossless mode + Bool bIndexTable; // index table present + Bool bTrimFlexbitsFlag; // trimmed flexbits indicated in packet header + Bool bUseHardTileBoundaries; //default is soft tile boundaries + size_t cNumChannels; + size_t cExtraPixelsTop; + size_t cExtraPixelsLeft; + size_t cExtraPixelsBottom; + size_t cExtraPixelsRight; + Bool bTranscode; // transcoding flag + U32 uQPMode; // 0/1: no dquant/with dquant, first bit for DC, second bit for LP, third bit for HP + U8 uiQPIndexDC[MAX_CHANNELS]; + U8 uiQPIndexLP[MAX_CHANNELS]; + U8 uiQPIndexHP[MAX_CHANNELS]; +}CCoreParameters; + +typedef struct CWMITile +{ + CWMIQuantizer * pQuantizerDC[MAX_CHANNELS]; + CWMIQuantizer * pQuantizerLP[MAX_CHANNELS]; + CWMIQuantizer * pQuantizerHP[MAX_CHANNELS]; + U8 cNumQPLP; + U8 cNumQPHP; + U8 cBitsLP; + U8 cBitsHP; + + Bool bUseDC; + Bool bUseLP; + U8 cChModeDC; + U8 cChModeLP[16]; + U8 cChModeHP[16]; +} CWMITile; + +#ifdef ARMOPT_COLORCONVERSION_C +#include "ARM_InvColorConversion.h" +#endif + +struct tagPostProcInfo{ + Int iMBDC; // DC of MB + U8 ucMBTexture; // MB texture : 0(flat) 1(horizontal) 2(vertical) 3(bumpy) + Int iBlockDC[4][4]; // DC of block + U8 ucBlockTexture[4][4]; // block texture: 0(flat) 1(horizontal) 2(vertical) 3(bumpy) +}; + +typedef struct CWMImageStrCodec { +#ifdef ARMOPT_COLORCONVERSION_C + CWMImageStrInvCCParam InvCCParam; +#endif + + size_t cbStruct; + + CWMImageInfo WMII; + CWMIStrCodecParam WMISCP; + CWMImageBufferInfo WMIBI; + CWMIMBInfo MBInfo; + + /** core parameters **/ + CCoreParameters m_param; + + struct CWMDecoderParameters *m_Dparam; // this is specified thru pointer because the same set of parameters may be used by multiple image planes + + U8 cSB; + + Bool m_bUVResolutionChange; + + Bool bTileExtraction; + + BitIOInfo * pIOHeader; + + Bool bUseHardTileBoundaries; //default is soft tile boundaries + + PixelI * pInterU; + PixelI * pInterV; + + //============== tile related info begins here =========== + // index table + size_t *pIndexTable; + + // current tile position + size_t cTileRow; + size_t cTileColumn; + + // tile boundary + Bool m_bCtxLeft; + Bool m_bCtxTop; + + Bool m_bResetRGITotals; + Bool m_bResetContext; + + CWMITile * pTile; + + // BitIOs + BitIOInfo ** m_ppBitIO; + size_t cNumBitIO; + size_t cHeaderSize; + + // coding contexts + struct CCodingContext *m_pCodingContext; + size_t cNumCodingContext; + + //============== tile related info ends here =========== + + size_t cNumOfQPIndex; // number of QP indexes + U8 cBitsDQUANT; // number of bits to encode DQUANT + + size_t cRow; // row for current macro block + size_t cColumn; // column for current macro block + + size_t cmbWidth; // macro block/image width + size_t cmbHeight; // macro block/image height + + size_t cbChannel; // byte/channel + + size_t mbX, mbY; + size_t tileX, tileY; + Bool bVertTileBoundary, bHoriTileBoundary; + Bool bOneMBLeftVertTB, bOneMBRightVertTB; //Macroblock to the left and to the right of tile boundaries + + PixelI iPredBefore[2][2]; + PixelI iPredAfter[2][2]; + + //================================ + // input data into + // macro block 3 of 2x2 working widow + //================================ + ImageDataProc Load; + //ImageDataProc Load2; + ImageDataProc Transform; + ImageDataProc TransformCenter; + + //================================ + ImageDataProc Quantize; + //ImageDataProc QuantizeLuma; + //ImageDataProc QuantizeChroma; + + //================================ + // process and store data from + // macro block 0 of 2x2 working window + //================================ + ImageDataProc ProcessTopLeft; + ImageDataProc ProcessTop; + ImageDataProc ProcessTopRight; + ImageDataProc ProcessLeft; + ImageDataProc ProcessCenter; + ImageDataProc ProcessRight; + ImageDataProc ProcessBottomLeft; + ImageDataProc ProcessBottom; + ImageDataProc ProcessBottomRight; + + + //================================ + // 2 MB working window for encoder + //================================ + PixelI *pPlane[MAX_CHANNELS]; + + //================================ + // 2 rows of MB buffer + //================================ + PixelI *a0MBbuffer[MAX_CHANNELS]; // pointer to start of previous MB row + PixelI *a1MBbuffer[MAX_CHANNELS]; // pointer to start of current MB row + PixelI *p0MBbuffer[MAX_CHANNELS]; // working pointer to start of previous row MB + PixelI *p1MBbuffer[MAX_CHANNELS]; // working pointer to start of current row MB + + //================================ + // downsampling buffer for UV + //================================ + PixelI * pResU; + PixelI * pResV; + + //================================ + // circular buffer for 2 MB rows: current row and previous row + //================================ + CWMIPredInfo *PredInfo[MAX_CHANNELS]; + CWMIPredInfo *PredInfoPrevRow[MAX_CHANNELS]; + CWMIPredInfo *pPredInfoMemory; + + struct WMPStream ** ppWStream; + +#ifdef _WIN32 + TCHAR **ppTempFile; +#else + char **ppTempFile; +#endif + + // interleaved alpha support - linked structure for Alpha channel + struct CWMImageStrCodec *m_pNextSC; + Bool m_bSecondary; + + //================================ + // Perf Timers + //================================ +#ifndef DISABLE_PERF_MEASUREMENT + Bool m_fMeasurePerf; + struct PERFTIMERSTATE *m_ptEndToEndPerf; // Measures from Init to Term, including I/O + struct PERFTIMERSTATE *m_ptEncDecPerf; // Measures time spent in ImageStrEncEncode/ImageStrDecDecode, excluding I/O +#endif // DISABLE_PERF_MEASUREMENT + + // postproc information for 2 MB rows: 0(previous row) 1(current row) + struct tagPostProcInfo * pPostProcInfo[MAX_CHANNELS][2]; +} CWMImageStrCodec; + + +//================================================================ +ERR WMPAlloc(void** ppv, size_t cb); +ERR WMPFree(void** ppv); + +//================================================================ +Void initMRPtr(CWMImageStrCodec*); +Void advanceMRPtr(CWMImageStrCodec*); +Void swapMRPtr(CWMImageStrCodec*); + +Int IDPEmpty(CWMImageStrCodec*); + +//================================================================ +extern const int dctIndex[3][16]; +extern const int blkOffset[16]; +extern const int blkOffsetUV[4]; +extern const int blkOffsetUV_422[8]; + +extern const U8 idxCC[16][16]; +extern const U8 idxCC_420[8][8]; + +extern const Char gGDISignature[]; + +//================================================================ +Int allocatePredInfo(CWMImageStrCodec*); +Void freePredInfo(CWMImageStrCodec*); +Void advanceOneMBRow(CWMImageStrCodec*); + +//================================================================ +// bit I/O +//================================================================ +Int allocateBitIOInfo(CWMImageStrCodec*); +Int setBitIOPointers(CWMImageStrCodec* pSC); + +#ifndef ARMOPT_BITIO +U32 peekBit16(BitIOInfo* pIO, U32 cBits); +U32 flushBit16(BitIOInfo* pIO, U32 cBits); +U32 getBit16(BitIOInfo* pIO, U32 cBits); +U32 getBool16(BitIOInfo* pIO); +I32 getBit16s(BitIOInfo* pIO, U32 cBits); +U32 getBit32(BitIOInfo* pIO, U32 cBits); +U32 flushToByte(BitIOInfo* pIO); +#endif // ARMOPT_BITIO + +Void putBit16z(BitIOInfo* pIO, U32 uiBits, U32 cBits); +Void putBit16(BitIOInfo* pIO, U32 uiBits, U32 cBits); +Void putBit32(BitIOInfo* pIO, U32 uiBits, U32 cBits); +Void fillToByte(BitIOInfo* pIO); + +U32 getSizeRead(BitIOInfo* pIO); +U32 getSizeWrite(BitIOInfo* pIO); + +U32 getPosRead(BitIOInfo* pIO); + +// safe function, solely for the convenience of test code +#ifndef ARMOPT_BITIO +U32 getBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 cBits); +#endif // ARMOPT_BITIO + +//================================================================ +// packet I/O +//================================================================ +ERR attachISRead(BitIOInfo* pIO, struct WMPStream* pWS, CWMImageStrCodec* pSC); +ERR readIS(CWMImageStrCodec* pSC, BitIOInfo* pIO); +ERR detachISRead(CWMImageStrCodec* pSC, BitIOInfo* pIO); + +ERR attachISWrite(BitIOInfo* pIO, struct WMPStream* pWS); +ERR writeIS(CWMImageStrCodec* pSC, BitIOInfo* pIO); +ERR detachISWrite(CWMImageStrCodec* pSC, BitIOInfo* pIO); + + +//================================================================ +// post processing for decoder +//================================================================ +Int initPostProc(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], size_t mbWidth, size_t iNumChannels); +Void termPostProc(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], size_t iNumChannels); +Void slideOneMBRow(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], size_t iNumChannels, size_t mbWidth, Bool top, Bool bottom); +Void updatePostProcInfo(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], PixelI * p, size_t mbX, size_t cc); +Void postProcMB(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], PixelI * p0, PixelI * p1, size_t mbX, size_t cc, Int threshold); +Void postProcBlock(struct tagPostProcInfo * strPostProcInfo[MAX_CHANNELS][2], PixelI * p0, PixelI * p1, size_t mbX, size_t cc, Int threshold); + +//================================================================ +// Simple BitIO access functions +//================================================================ +typedef struct tagSimpleBitIO +{ + struct WMPStream* pWS; + U32 cbRead; + U8 bAccumulator; + U32 cBitLeft; +} SimpleBitIO; + +ERR attach_SB(SimpleBitIO* pSB, struct WMPStream* pWS); +U32 getBit32_SB(SimpleBitIO* pSB, U32 cBits); +Void flushToByte_SB(SimpleBitIO* pSB); +U32 getByteRead_SB(SimpleBitIO* pSB); +ERR detach_SB(SimpleBitIO* pSB); + +//---------------------------------------------------------------- +EXTERN_C Bool EOSWS_File(struct WMPStream* pWS); + +EXTERN_C ERR ReadWS_File(struct WMPStream* pWS, void* pv, size_t cb); +EXTERN_C ERR WriteWS_File(struct WMPStream* pWS, const void* pv, size_t cb); +//EXTERN_C ERR GetLineWS_File(struct WMPStream* pWS, void* pv, size_t cb); + +EXTERN_C ERR SetPosWS_File(struct WMPStream* pWS, size_t offPos); +EXTERN_C ERR GetPosWS_File(struct WMPStream* pWS, size_t* poffPos); + +//---------------------------------------------------------------- +EXTERN_C Bool EOSWS_Memory(struct WMPStream* pWS); + +EXTERN_C ERR ReadWS_Memory(struct WMPStream* pWS, void* pv, size_t cb); +EXTERN_C ERR WriteWS_Memory(struct WMPStream* pWS, const void* pv, size_t cb); +//EXTERN_C ERR GetLineWS_Memory(struct WMPStream* pWS, void* pv, size_t cb); + +EXTERN_C ERR SetPosWS_Memory(struct WMPStream* pWS, size_t offPos); +EXTERN_C ERR GetPosWS_Memory(struct WMPStream* pWS, size_t* poffPos); + +//EXTERN_C ERR GetPtrWS_Memory(struct WMPStream* pWS, size_t align, U8** ppb); +//---------------------------------------------------------------- +EXTERN_C Bool EOSWS_List(struct WMPStream* pWS); + +EXTERN_C ERR ReadWS_List(struct WMPStream* pWS, void* pv, size_t cb); +EXTERN_C ERR WriteWS_List(struct WMPStream* pWS, const void* pv, size_t cb); + +EXTERN_C ERR SetPosWS_List(struct WMPStream* pWS, size_t offPos); +EXTERN_C ERR GetPosWS_List(struct WMPStream* pWS, size_t* poffPos); + +EXTERN_C ERR CreateWS_List(struct WMPStream** ppWS); +EXTERN_C ERR CloseWS_List(struct WMPStream** ppWS); + +/********************************************************************/ +// Stuff related to scale/spatial ordering +typedef struct PacketInfo +{ + BAND m_iBand; + size_t m_iSize; + size_t m_iOffset; + struct PacketInfo *m_pNext; +} PacketInfo; +/********************************************************************/ + +/********************************************************************/ +const static Int blkIdxByRow[4][4] = {{0, 1, 4, 5}, {2, 3, 6, 7}, {8, 9, 12, 13}, {10, 11, 14, 15}}; +const static Int blkIdxByColumn[4][4] = {{0, 2, 8, 10}, {1, 3, 9, 11},{4, 6, 12, 14},{5, 7, 13, 15}}; + +Int getACPredMode(CWMIMBInfo *, COLORFORMAT); +Int getDCACPredMode(CWMImageStrCodec *, size_t); +Void updatePredInfo(CWMImageStrCodec* pSC, CWMIMBInfo *, size_t, COLORFORMAT); + +Int AllocateCodingContextDec(struct CWMImageStrCodec *pSC, Int iNumContexts); +Void ResetCodingContext(CCodingContext *pContext); +Void getTilePos(CWMImageStrCodec* pSC, size_t mbX, size_t mbY); +Void InitZigzagScan(CCodingContext * pSC); +Int checkImageBuffer(CWMImageStrCodec *, size_t, size_t); + +//U32 log2(U32); + +//DQUANT stuff +EXTERN_C Void remapQP(CWMIQuantizer *, I32, Bool); +Int allocateTileInfo(CWMImageStrCodec *); +Void freeTileInfo(CWMImageStrCodec *); +Int allocateQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], size_t, size_t); +Void freeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS]); +Void setUniformQuantizer(CWMImageStrCodec *, size_t); +Void useDCQuantizer(CWMImageStrCodec *, size_t); +Void useLPQuantizer(CWMImageStrCodec *, size_t, size_t); +Void formatQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], U8, size_t, size_t, Bool, Bool); +U8 dquantBits(U8); + +#ifdef ARMOPT_BITIO +#define peekBit16 peekBits +#define flushBit16 flushBits +#define getBit16 getBits +#define getBit32 getBits +#define getBit16s getBitsS +#define getBool16(pIO) getBits(pIO, 1) + +U32 peekBits(BitIOInfo* pIO, U32 cBits); +void flushBits(BitIOInfo* pIO, U32 cBits); +U32 getBits(BitIOInfo* pIO, U32 cBits); +U32 getBitsS(BitIOInfo* pIO, U32 cBits); +void flushToByte(BitIOInfo* pIO); +#endif // ARMOPT_BITIO + +/************************************************************************* + Bitio defines +*************************************************************************/ +#define PEEKBIT16(pIO, cBits) \ + assert(0 <= (I32)cBits && cBits <= 16);\ + return (pIO->uiAccumulator >> (32 - cBits/* - pIO->cBitsUsed*/)); + +#define FLUSHBIT16(pIO, cBits) \ + assert(0 <= (I32)cBits && cBits <= 16);\ + assert((pIO->iMask & 1) == 0);\ + pIO->cBitsUsed += cBits;\ + pIO->pbCurrent = MASKPTR(pIO->pbCurrent + ((pIO->cBitsUsed >> 3)/* & 2*/), pIO->iMask);\ + pIO->cBitsUsed &= 16 - 1;\ + pIO->uiAccumulator = LOAD16(pIO->pbCurrent) << pIO->cBitsUsed;\ + return 0; +// pIO->uiAccumulator = LOAD16(pIO->pbCurrent) & ((U32)(-1) >> pIO->cBitsUsed);\ + +void OutputPerfTimerReport(CWMImageStrCodec *pState); + +#if (defined(_WIN32) && !defined(UNDER_CE)) || (defined(UNDER_CE) && defined(_ARM_)) +// WinCE ARM and Desktop x86 +#else +// other platform +#ifdef _BIG__ENDIAN_ +#define _byteswap_ulong(x) (x) +#else // _BIG__ENDIAN_ +U32 _byteswap_ulong(U32 bits); +#endif // _BIG__ENDIAN_ +#endif diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.o new file mode 100644 index 0000000..393aec4 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/strcodec.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/windowsmediaphoto.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/windowsmediaphoto.h new file mode 100644 index 0000000..4d7ac2f --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/windowsmediaphoto.h @@ -0,0 +1,515 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright � Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// � Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// � Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#ifndef WMI_WINDOWSMEDIAPHOTO_H +#define WMI_WINDOWSMEDIAPHOTO_H + +//================================================================ +#include +#include +#include +#include + +#if defined(__cplusplus) && !defined(EXTERN_C) +#define EXTERN_C extern "C" +#elif !defined(EXTERN_C)// __cplusplus +#define EXTERN_C extern +#endif // __cplusplus + +/******************************************************************************** + Type definitions +********************************************************************************/ +typedef int Bool; +typedef char Char; +typedef double Double; +typedef int Int; +typedef signed char I8; +typedef short I16; // 16 bit int +typedef int I32; +typedef long Long; +typedef unsigned char PixelC; +typedef int PixelI; +typedef unsigned int UInt; +typedef unsigned long ULong; +typedef unsigned char U8; // 8 bit uint +typedef unsigned short U16; +typedef unsigned int U32; // 32 bit uint +typedef void Void; + +typedef void* CTXSTRCODEC; + + +#define REENTRANT_MODE 1 +/* + DESCRIPTION OF COMPILER FLAG REENTRANT_MODE: + + //#define REENTRANT_MODE 1 + + This compiler flag is related to the capability of banded decode + (decoding only one MB row of the source JPEG XR image at a time). + + With REENTRANT_MODE defined, the decoder decodes one MB row on each call to + ImageStrDecDecode(). + + The decoder acts as if it can only write to the single MBRow whose pointer was passed to it. + This acts as a proof of concept that the API would work if you passed it a small buffer + on each call to ImageStrDecDecode(). + + The REENTRANT_MODE flag only works when the output image is in Orientations 0, 1 + (vertically flipped) or 2 (horizontally flipped). + + With REENTRANT_MODE defined, the function PKImageDecode_Copy_WMP() + decodes only as far as the pRect parameter indicates. The width of the rectangle must be the width + of the image, but on each call, this function will decode the image up to the end of the MB Row + which contains the i-th pixel row, where i = pRect->Y. + + A target use of this version would be to have PKImageDecode_Copy_WMP() called in a loop, once for + each MB row. On each call, pRect would specify a 1-MB-Row-tall rectangle that is the width of the + image. The decoder state is preserved until the Decoder finishes decoding the image. + + If, at a certain point, a request is made for a rectangle _above_ the last row decoded, then the + decoder instance is terminated and re-initiated, and decoding re-starts, going from the beginning + of the image to the end of the current rectangle. + + *** + + We've chosen to uncomment-out this definition in this header file. An alternate method would be + to allow the user to define this in the PREPROCESSOR DEFINITIONS section of the properties page + for each of the following projects: CommonLib, DecodeLib, JXRDecApp and JXRGlueLib. + +*/ +/************************************************************************* + enums +*************************************************************************/ +typedef enum { + ICERR_OK = 0, ICERR_ERROR = -1 +} ERR_CODE; + +typedef enum BITDEPTH { + BD_SHORT, BD_LONG, + + /* add new BITDEPTH here */ BD_MAX +} BITDEPTH; + +typedef enum BITDEPTH_BITS { + // regular ones + BD_1, //White is foreground + BD_8, BD_16, BD_16S, BD_16F, BD_32, BD_32S, BD_32F, + + // irregular ones + BD_5, BD_10, BD_565, + + /* add new BITDEPTH_BITS here */ BDB_MAX, + + BD_1alt = 0xf, //Black is foreground +} BITDEPTH_BITS; + +typedef enum OVERLAP { + OL_NONE = 0, OL_ONE, OL_TWO, + + /* add new OVERLAP here */ OL_MAX +} OVERLAP; + +typedef enum BITSTREAMFORMAT { + SPATIAL = 0, // spatial order + FREQUENCY, // frequency order +} BITSTREAMFORMAT; + +typedef enum COLORFORMAT { + Y_ONLY = 0, + YUV_420 = 1, + YUV_422 = 2, + YUV_444 = 3, + CMYK = 4, + //CMYKDIRECT = 5, + NCOMPONENT = 6, + + // these are external-only + CF_RGB = 7, + CF_RGBE = 8, + + /* add new COLORFORMAT here */ CFT_MAX +} COLORFORMAT; + +// rotation and flip +typedef enum ORIENTATION { + // CRW: Clock Wise 90% Rotation; FlipH: Flip Horizontally; FlipV: Flip Vertically + // Peform rotation FIRST! + // CRW FlipH FlipV + O_NONE = 0, // 0 0 0 + O_FLIPV, // 0 0 1 + O_FLIPH, // 0 1 0 + O_FLIPVH, // 0 1 1 + O_RCW, // 1 0 0 + O_RCW_FLIPV, // 1 0 1 + O_RCW_FLIPH, // 1 1 0 + O_RCW_FLIPVH, // 1 1 1 + /* add new ORIENTATION here */ O_MAX +} ORIENTATION; + +typedef enum SUBBAND { + SB_ALL = 0, // keep all subbands + SB_NO_FLEXBITS, // skip flex bits + SB_NO_HIGHPASS, // skip highpass + SB_DC_ONLY, // skip lowpass and highpass, DC only + SB_ISOLATED, // not decodable + /* add new SUBBAND here */ SB_MAX +} SUBBAND; + +enum { RAW = 0, BMP = 1, PPM = 2, TIF = 3, HDR = 4, IYUV = 5, YUV422 = 6, YUV444 = 7}; + +typedef enum {ERROR_FAIL = -1, SUCCESS_DONE, PRE_READ_HDR, PRE_SETUP, PRE_DECODE, POST_READ_HDR } WMIDecoderStatus; + +#ifndef FALSE +#define FALSE 0 +#endif // FALSE + +#ifndef TRUE +#define TRUE 1 +#endif // TRUE + +#define MAX_CHANNELS 16 +#define LOG_MAX_TILES 12 +#define MAX_TILES (1 << LOG_MAX_TILES) + + +//================================================================ +// Codec-specific constants +#define MB_WIDTH_PIXEL 16 +#define MB_HEIGHT_PIXEL 16 + +#define BLK_WIDTH_PIXEL 4 +#define BLK_HEIGHT_PIXEL 4 + +#define MB_WIDTH_BLK 4 +#define MB_HEIGHT_BLK 4 + +// The codec operates most efficiently when the framebuffers for encoder input +// and decoder output are: 1) aligned on a particular boundary, and 2) the stride +// is also aligned to this boundary (so that each scanline is also aligned). +// This boundary is defined below. +#define FRAMEBUFFER_ALIGNMENT 128 + + +//================================================================ +#define WMP_errSuccess 0 + +#define WMP_errFail -1 +#define WMP_errNotYetImplemented -2 +#define WMP_errAbstractMethod -3 + +#define WMP_errOutOfMemory -101 +#define WMP_errFileIO -102 +#define WMP_errBufferOverflow -103 +#define WMP_errInvalidParameter -104 +#define WMP_errInvalidArgument -105 +#define WMP_errUnsupportedFormat -106 +#define WMP_errIncorrectCodecVersion -107 +#define WMP_errIndexNotFound -108 +#define WMP_errOutOfSequence -109 +#define WMP_errNotInitialized -110 +#define WMP_errMustBeMultipleOf16LinesUntilLastCall -111 +#define WMP_errPlanarAlphaBandedEncRequiresTempFile -112 +#define WMP_errAlphaModeCannotBeTranscoded -113 +#define WMP_errIncorrectCodecSubVersion -114 + + +//================================================================ +typedef int ERR; + +#define Failed(err) ((err)<0) + +#define CRLF "\r\n" + +#define CT_ASSERT(exp, uniq) typedef char __CT_ASSERT__##uniq[(exp) ? 1 : -1] // Caller must provide a unique tag, or this fails to compile under GCC + +#if defined(_DEBUG) || defined(DBG) +#define Report(err, szExp, szFile, nLine) \ + fprintf(stderr, "FAILED: %ld=%s" CRLF, (err), (szExp)); \ + fprintf(stderr, " %s:%ld" CRLF, (szFile), (nLine)); \ + +#else +#define Report(err, szExp, szFile, lLine) err = err +#endif + +#define Call(exp) \ + if (Failed(err = (exp))) \ + { \ + Report(err, #exp, __FILE__, (long)__LINE__); \ + goto Cleanup; \ + } \ + else err = err + +#define CallIgnoreError(errTmp, exp) \ + if (Failed(errTmp = (exp))) \ + { \ + Report(errTmp, #exp, __FILE__, (long)__LINE__); \ + } \ + else errTmp = errTmp + + +#define Test(exp, err) Call((exp) ? WMP_errSuccess : (err)) +#define FailIf(exp, err) Call((exp) ? (err) : WMP_errSuccess) + +//================================================================ +// WMPStream interface +//================================================================ +struct WMPStream +{ + union + { + struct tagFile + { + FILE* pFile; + } file; + + struct tagBuf + { + U8* pbBuf; + size_t cbBuf; + size_t cbCur; + size_t cbBufCount; + } buf; + + void* pvObj; + } state; + + Bool fMem; + + ERR (*Close)(struct WMPStream** pme); + + Bool (*EOS)(struct WMPStream* me); + + ERR (*Read)(struct WMPStream* me, void* pv, size_t cb); + ERR (*Write)(struct WMPStream* me, const void* pv, size_t cb); + //ERR (*GetLine)(struct WMPStream* me, void* pv, size_t cb); + + ERR (*SetPos)(struct WMPStream* me, size_t offPos); + ERR (*GetPos)(struct WMPStream* me, size_t* poffPos); +}; + +EXTERN_C ERR CreateWS_File(struct WMPStream** ppWS, const char* szFilename, const char* szMode); +EXTERN_C ERR CloseWS_File(struct WMPStream** ppWS); + +EXTERN_C ERR CreateWS_Memory(struct WMPStream** ppWS, void* pv, size_t cb); +EXTERN_C ERR CloseWS_Memory(struct WMPStream** ppWS); + + +//================================================================ +// Enc/Dec data structure +//================================================================ +typedef struct tagCWMImageInfo { + size_t cWidth; + size_t cHeight; + COLORFORMAT cfColorFormat; + BITDEPTH_BITS bdBitDepth; + size_t cBitsPerUnit; + size_t cLeadingPadding; // number of leading padding + Bool bRGB; // true: RGB; false: BGR + U8 cChromaCenteringX; // Relative location of Chroma w.r.t Luma + U8 cChromaCenteringY; // Relative location of Chroma w.r.t Luma + + // Region of interest decoding + size_t cROILeftX; + size_t cROIWidth; + size_t cROITopY; + size_t cROIHeight; + + // thumbnail decode + Bool bSkipFlexbits; + size_t cThumbnailWidth; + size_t cThumbnailHeight; + + // image orientation + ORIENTATION oOrientation; + + // post processing + U8 cPostProcStrength; // 0(none) 1(light) 2(medium) 3(strong) 4(very strong) + + // user buffer is always padded to whole MB + Bool fPaddedUserBuffer; +} CWMImageInfo; + +typedef struct tagCWMIStrCodecParam { + Bool bVerbose; + + // for macroblock quantization (DQUANT) + U8 uiDefaultQPIndex; + U8 uiDefaultQPIndexYLP; + U8 uiDefaultQPIndexYHP; + U8 uiDefaultQPIndexU; + U8 uiDefaultQPIndexULP; + U8 uiDefaultQPIndexUHP; + U8 uiDefaultQPIndexV; + U8 uiDefaultQPIndexVLP; + U8 uiDefaultQPIndexVHP; + U8 uiDefaultQPIndexAlpha; + + COLORFORMAT cfColorFormat; + BITDEPTH bdBitDepth; + OVERLAP olOverlap; + BITSTREAMFORMAT bfBitstreamFormat; + size_t cChannel; // number of color channels including alpha + U8 uAlphaMode; // 0:no alpha 1: alpha only else: something + alpha + SUBBAND sbSubband; // which subbands to keep + U8 uiTrimFlexBits; + + struct WMPStream* pWStream; + size_t cbStream; + + // tiling info + U32 cNumOfSliceMinus1V; // # of vertical slices + U32 uiTileX[MAX_TILES]; // width in MB of each veritical slice + U32 cNumOfSliceMinus1H; // # of horizontal slices + U32 uiTileY[MAX_TILES]; // height in MB of each horizontal slice + + //32f and 32s conversion parameters + U8 nLenMantissaOrShift; + I8 nExpBias; + + Bool bBlackWhite; + + Bool bUseHardTileBoundaries; //default is soft tile boundaries + + Bool bProgressiveMode; //default is sequential mode + + Bool bYUVData; //default is cfColorFormat data + + Bool bUnscaledArith; //force unscaled arithmetic + + // Perf measurement + Bool fMeasurePerf; +} CWMIStrCodecParam; + +typedef struct tagCWMImageBufferInfo { + void* pv; // pointer to scanline buffer + size_t cLine; // count of scanlines + size_t cbStride; // count of BYTE for stride +#ifdef REENTRANT_MODE + unsigned int uiFirstMBRow; // Current First MB Row being decoded + unsigned int uiLastMBRow; // Current Last MB Row being decoded + size_t cLinesDecoded; // Number of lines decoded and returned in low-mem mode +#endif // REENTRANT_MODE +} CWMImageBufferInfo; + + + + +/****************************************************************/ +/* Encode API */ +/****************************************************************/ +EXTERN_C Int ImageStrEncInit( + CWMImageInfo* pII, + CWMIStrCodecParam *pSCP, + CTXSTRCODEC* pctxSC); + +EXTERN_C Int ImageStrEncEncode( + CTXSTRCODEC ctxSC, + const CWMImageBufferInfo* pBI); + +EXTERN_C Int ImageStrEncTerm( + CTXSTRCODEC ctxSC); + + +/****************************************************************/ +/* Decode API */ +/****************************************************************/ +struct CWMImageStrCodec; + +EXTERN_C Int ImageStrDecGetInfo( + CWMImageInfo* pII, + CWMIStrCodecParam *pSCP); + +EXTERN_C Int ImageStrDecInit( + CWMImageInfo* pII, + CWMIStrCodecParam *pSCP, + CTXSTRCODEC* pctxSC); + +EXTERN_C Int ImageStrDecDecode( + CTXSTRCODEC ctxSC, + const CWMImageBufferInfo* pBI +#ifdef REENTRANT_MODE + , size_t *pcDecodedLines +#endif + ); + +EXTERN_C Int ImageStrDecTerm( + CTXSTRCODEC ctxSC); + +EXTERN_C Int WMPhotoValidate( + CWMImageInfo * pII, + CWMIStrCodecParam * pSCP); + + +/****************************************************************/ +/* Transcoding API */ +/****************************************************************/ +typedef struct tagCWMTranscodingParam { + size_t cLeftX; + size_t cWidth; + size_t cTopY; + size_t cHeight; // interested region + + BITSTREAMFORMAT bfBitstreamFormat; // desired bitstream format +// COLORFORMAT cfColorFormat; // desired color format + U8 uAlphaMode; // 0:no alpha 1: alpha only else: something + alpha + SUBBAND sbSubband; // which subbands to keep + ORIENTATION oOrientation; // flip / right angle rotation + Bool bIgnoreOverlap; +} CWMTranscodingParam; + +EXTERN_C Int WMPhotoTranscode( + struct WMPStream* pStreamDec, // input bitstrean + struct WMPStream* pStreamEnc, // output bitstream + CWMTranscodingParam* pParam // transcoding parameters +); + +typedef struct tagCWMDetilingParam { + size_t cWidth; + size_t cHeight; // image size + size_t cChannel; // # of channels + OVERLAP olOverlap; // overlap + BITDEPTH_BITS bdBitdepth; // bit depth + + // tiling info + U32 cNumOfSliceMinus1V; // # of vertical slices + U32 uiTileX[MAX_TILES]; // position in MB of each veritical slice + U32 cNumOfSliceMinus1H; // # of horizontal slices + U32 uiTileY[MAX_TILES]; // position in MB of each horizontal slice + + // image info + void * pImage; + size_t cbStride; +} CWMDetilingParam; + +EXTERN_C Int WMPhotoDetile( + CWMDetilingParam * pParam // detiling parameters +); + +#endif // WMI_WINDOWSMEDIAPHOTO_H + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/xplatform_image.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/xplatform_image.h new file mode 100644 index 0000000..645edca --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/sys/xplatform_image.h @@ -0,0 +1,84 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** + +#ifndef XPLATFORM_IMAGE_H +#define XPLATFORM_IMAGE_H + +#ifdef __ANSI__ +// ANSI +#define FORCE_INLINE +#define CDECL +#define UINTPTR_T unsigned int +#define INTPTR_T int +#define DECLSPEC_ALIGN(bytes) +#endif // __ANSI__ + + +//#if defined(_WIN32) +#if defined(_WIN32) && !defined(UNDER_CE) // _WIN32 seems to be defined always in VS2005 for ARM platform +// x86 +//#define CDECL __cdecl +#define DECLSPEC_ALIGN(bytes) __declspec(align(bytes)) +#endif // x86 + + +#if defined(_ARM_) || defined(UNDER_CE) +// ARM, WinCE +#define FORCE_INLINE inline +#define CDECL +#define UINTPTR_T unsigned int +#define INTPTR_T int +#define DECLSPEC_ALIGN(bytes) + +// parser +#define FULL_PATH_CONFIG_FILE_ENCODE "\\ConfigFile_encode.txt" +#define FULL_PATH_CONFIG_FILE_DECODE "\\ConfigFile_decode.txt" +#define MAX_ARGC 14 +#define MaxCharReadCount 10 +#define MAX_FNAME 256 +#define DELIMITER "filelist:" +#define CODEC_ENCODE "encode" +#define CODEC_DECODE "decode" +#define PHOTON "ptn" +#define OUTRAW "raw" +#define OUTBMP "bmp" +#define OUTPPM "ppm" +#define OUTTIF "tif" +#define OUTHDR "hdr" +#define OUTIYUV "iyuv" +#define OUTYUV422 "yuv422" +#define OUTYUV444 "yuv444" +int XPLATparser(char *pcARGV[], char *pcCodec); +void freeXPLATparser(int iARGC, char *pcARGV[]); + +// WinCE intrinsic +#include +#endif // ARM, WinCE + +#endif // XPLATFORM_IMAGE_H + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/x86/x86.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/x86/x86.h new file mode 100644 index 0000000..a519137 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/image/x86/x86.h @@ -0,0 +1,58 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#pragma once + +#include +#include + +//================================ +// bitio functions +//================================ +#define PACKETLENGTH (1U<<12) // 4kB + +#define readIS_L1(pSC, pIO) readIS(pSC, pIO) +#define readIS_L2(pSC, pIO) (void)(pSC, pIO) + +#define writeIS_L1(pSC, pIO) writeIS(pSC, pIO) +#define writeIS_L2(pSC, pIO) (void)(pSC, pIO) + + +//================================ +// common defines +//================================ +#define FORCE_INLINE __forceinline +#define UINTPTR_T uintptr_t +#define INTPTR_T intptr_t + + +//================================ +// quantization optimization +//================================ +#define RECIP_QUANT_OPT + + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.c new file mode 100644 index 0000000..ca1663a --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.c @@ -0,0 +1,930 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include +#include + +#define INITGUID +#include + +//================================================================ +const PKIID IID_PKImageScanEncode = 1; +const PKIID IID_PKImageFrameEncode = 2; + +const PKIID IID_PKImageUnsupported = 100; +const PKIID IID_PKImageWmpEncode = 101; + +const PKIID IID_PKImageWmpDecode = 201; + +//================================================================ +// Misc supporting functions +//================================================================ +ERR PKAlloc(void** ppv, size_t cb) +{ + *ppv = calloc(1, cb); + return *ppv ? WMP_errSuccess : WMP_errOutOfMemory; +} + + +ERR PKFree(void** ppv) +{ + if (ppv) + { + free(*ppv); + *ppv = NULL; + } + + return WMP_errSuccess; +} + +ERR PKAllocAligned(void** ppv, size_t cb, size_t iAlign) +{ + U8 *pOrigPtr; + U8 *pReturnedPtr; + size_t iAlignmentCorrection; + const size_t c_cbBlockSize = cb + sizeof(void*) + iAlign - 1; + + *ppv = NULL; + pOrigPtr = calloc(1, c_cbBlockSize); + if (NULL == pOrigPtr) + return WMP_errOutOfMemory; + + iAlignmentCorrection = iAlign - ((size_t)pOrigPtr % iAlign); + if (iAlignmentCorrection < sizeof(void*)) + // Alignment correction won't leave us enough space to store pOrigPtr - advance to next block + iAlignmentCorrection += iAlign; + + assert(iAlignmentCorrection >= sizeof(void*)); // Alignment correction must have space for pOrigPtr + assert(iAlignmentCorrection + cb <= c_cbBlockSize); // Don't exceed right edge of memory block + + pReturnedPtr = pOrigPtr + iAlignmentCorrection; + *(void**)(pReturnedPtr - sizeof(void*)) = pOrigPtr; + + assert(0 == ((size_t)pReturnedPtr % iAlign)); // Are we in fact aligned? + *ppv = pReturnedPtr; + return WMP_errSuccess; +} + +ERR PKFreeAligned(void** ppv) +{ + if (ppv && *ppv) + { + U8 **ppOrigPtr = (U8**)((U8*)(*ppv) - sizeof(void*)); + assert(*ppOrigPtr <= (U8*)ppOrigPtr); // Something's wrong if pOrigPtr points forward + free(*ppOrigPtr); + *ppv = NULL; + } + return WMP_errSuccess; +} + + + +int PKStrnicmp(const char* s1, const char* s2, size_t c) +{ + for(; tolower(*s1) == tolower(*s2) && *s1 && *s2 && c; ++s1, ++s2, --c); + return c ? *s1 - *s2 : 0; +} + +static const PKPixelInfo pixelInfo[] = +{ + {&GUID_PKPixelFormatDontCare, 1, Y_ONLY, BD_8, 8, PK_pixfmtNul, 0, 0, 0, 0}, + + // Gray + //{&GUID_PKPixelFormat2bppGray, 1, Y_ONLY, BD_8, 2, PK_pixfmtNul}, + //{&GUID_PKPixelFormat4bppGray, 1, Y_ONLY, BD_8, 4, PK_pixfmtNul}, + + {&GUID_PKPixelFormatBlackWhite, 1, Y_ONLY, BD_1, 1, PK_pixfmtNul, 1, 1, 1, 1},//BlackIsZero is default for GUID_PKPixelFormatBlackWhite + {&GUID_PKPixelFormatBlackWhite, 1, Y_ONLY, BD_1, 1, PK_pixfmtNul, 0, 1, 1, 1},//WhiteIsZero + {&GUID_PKPixelFormat8bppGray, 1, Y_ONLY, BD_8, 8, PK_pixfmtNul, 1, 1, 8, 1}, + {&GUID_PKPixelFormat16bppGray, 1, Y_ONLY, BD_16, 16, PK_pixfmtNul, 1, 1, 16, 1}, + {&GUID_PKPixelFormat16bppGrayFixedPoint, 1, Y_ONLY, BD_16S, 16, PK_pixfmtNul, 1, 1, 16, 2}, + {&GUID_PKPixelFormat16bppGrayHalf, 1, Y_ONLY, BD_16F, 16, PK_pixfmtNul, 1, 1, 16, 3}, + //{&GUID_PKPixelFormat32bppGray, 1, Y_ONLY, BD_32, 32, PK_pixfmtNul, 1, 1, 32, 1}, + {&GUID_PKPixelFormat32bppGrayFixedPoint, 1, Y_ONLY, BD_32S, 32, PK_pixfmtNul, 1, 1, 32, 2}, + {&GUID_PKPixelFormat32bppGrayFloat, 1, Y_ONLY, BD_32F, 32, PK_pixfmtNul, 1, 1, 32, 3}, + + // RGB + {&GUID_PKPixelFormat24bppRGB, 3, CF_RGB, BD_8, 24, PK_pixfmtNul, 2, 3, 8, 1}, + {&GUID_PKPixelFormat24bppBGR, 3, CF_RGB, BD_8, 24, PK_pixfmtBGR, 2, 3, 8, 1}, + {&GUID_PKPixelFormat32bppRGB, 3, CF_RGB, BD_8, 32, PK_pixfmtNul, 2, 3, 8, 1}, + {&GUID_PKPixelFormat32bppBGR, 3, CF_RGB, BD_8, 32, PK_pixfmtBGR, 2, 3, 8, 1}, + {&GUID_PKPixelFormat48bppRGB, 3, CF_RGB, BD_16, 48, PK_pixfmtNul, 2, 3, 16, 1}, + {&GUID_PKPixelFormat48bppRGBFixedPoint, 3, CF_RGB, BD_16S, 48, PK_pixfmtNul, 2, 3, 16, 2}, + {&GUID_PKPixelFormat48bppRGBHalf, 3, CF_RGB, BD_16F, 48, PK_pixfmtNul, 2, 3, 16, 3}, + {&GUID_PKPixelFormat64bppRGBFixedPoint, 3, CF_RGB, BD_16S, 64, PK_pixfmtNul, 2, 3, 16, 2}, + {&GUID_PKPixelFormat64bppRGBHalf, 3, CF_RGB, BD_16F, 64, PK_pixfmtNul, 2, 3, 16, 3}, + //{&GUID_PKPixelFormat96bppRGB, 3, CF_RGB, BD_32, 96, PK_pixfmtNul, 2, 3, 32, 1}, + {&GUID_PKPixelFormat96bppRGBFixedPoint, 3, CF_RGB, BD_32S, 96, PK_pixfmtNul, 2, 3, 32, 2}, + {&GUID_PKPixelFormat96bppRGBFloat, 3, CF_RGB, BD_32F, 96, PK_pixfmtNul, 2, 3, 32, 3}, + {&GUID_PKPixelFormat128bppRGBFixedPoint, 3, CF_RGB, BD_32S, 128, PK_pixfmtNul, 2, 3, 32, 2}, + {&GUID_PKPixelFormat128bppRGBFloat, 3, CF_RGB, BD_32F, 128, PK_pixfmtNul, 2, 3, 32, 3}, + + // RGBA + {&GUID_PKPixelFormat32bppBGRA, 4, CF_RGB, BD_8, 32, PK_pixfmtHasAlpha | PK_pixfmtBGR, 2, 4, 8, 1}, + {&GUID_PKPixelFormat32bppRGBA, 4, CF_RGB, BD_8, 32, PK_pixfmtHasAlpha, 2, 4, 8, 1}, + {&GUID_PKPixelFormat64bppRGBA, 4, CF_RGB, BD_16, 64, PK_pixfmtHasAlpha, 2, 4, 16, 1}, + {&GUID_PKPixelFormat64bppRGBAFixedPoint, 4, CF_RGB, BD_16S, 64, PK_pixfmtHasAlpha, 2, 4, 16, 2}, + {&GUID_PKPixelFormat64bppRGBAHalf, 4, CF_RGB, BD_16F, 64, PK_pixfmtHasAlpha, 2, 4, 16, 3}, + //{&GUID_PKPixelFormat128bppRGBA, 4, CF_RGB, BD_32, 128, PK_pixfmtHasAlpha, 2, 4, 32, 1}, + {&GUID_PKPixelFormat128bppRGBAFixedPoint, 4, CF_RGB, BD_32S, 128, PK_pixfmtHasAlpha, 2, 4, 32, 2}, + {&GUID_PKPixelFormat128bppRGBAFloat, 4, CF_RGB, BD_32F, 128, PK_pixfmtHasAlpha, 2, 4, 32, 3}, + + // PRGBA + {&GUID_PKPixelFormat32bppPBGRA, 4, CF_RGB, BD_8, 32, PK_pixfmtHasAlpha | PK_pixfmtPreMul | PK_pixfmtBGR, 2, 4, 8, 1}, + {&GUID_PKPixelFormat32bppPRGBA, 4, CF_RGB, BD_8, 32, PK_pixfmtHasAlpha | PK_pixfmtPreMul, 2, 4, 8, 1}, + {&GUID_PKPixelFormat64bppPRGBA, 4, CF_RGB, BD_16, 64, PK_pixfmtHasAlpha | PK_pixfmtPreMul, 2, 4, 16, 1}, + //{&GUID_PKPixelFormat64bppPRGBAFixedPoint, 4, CF_RGB, BD_16S, 64, PK_pixfmtHasAlpha, 2, 4, 16, 2}, + //{&GUID_PKPixelFormat64bppPRGBAHalf, 4, CF_RGB, BD_16F, 64, PK_pixfmtHasAlpha, 2, 4, 16, 3}, + //{&GUID_PKPixelFormat128bppPRGBAFixedPoint, 4, CF_RGB, BD_32S, 128, PK_pixfmtHasAlpha, 2, 4, 32, 2}, + {&GUID_PKPixelFormat128bppPRGBAFloat, 4, CF_RGB, BD_32F, 128, PK_pixfmtHasAlpha | PK_pixfmtPreMul, 2, 4, 32, 3}, + + // Packed formats + {&GUID_PKPixelFormat16bppRGB555, 3, CF_RGB, BD_5, 16, PK_pixfmtNul, 2, 3, 5, 1}, + {&GUID_PKPixelFormat16bppRGB565, 3, CF_RGB, BD_565, 16, PK_pixfmtNul, 2, 3, 6, 1}, + {&GUID_PKPixelFormat32bppRGB101010, 3, CF_RGB, BD_10, 32, PK_pixfmtNul, 2, 3, 10, 1}, + + // CMYK + {&GUID_PKPixelFormat32bppCMYK, 4, CMYK, BD_8, 32, PK_pixfmtNul, 5, 4, 8, 1}, + {&GUID_PKPixelFormat40bppCMYKAlpha, 5, CMYK, BD_8, 40, PK_pixfmtHasAlpha, 5, 5, 8, 1}, + + {&GUID_PKPixelFormat64bppCMYK, 4, CMYK, BD_16, 64, PK_pixfmtNul, 5, 4, 16, 1}, + {&GUID_PKPixelFormat80bppCMYKAlpha, 5, CMYK, BD_16, 80, PK_pixfmtHasAlpha, 5, 5, 16, 1}, + + // N_CHANNEL + {&GUID_PKPixelFormat24bpp3Channels, 3, NCOMPONENT, BD_8, 24, PK_pixfmtNul, PK_PI_NCH, 3, 8, 1},//the N channel TIF by PS has PhotometricInterpretation of PK_PI_RGB + {&GUID_PKPixelFormat32bpp4Channels, 4, NCOMPONENT, BD_8, 32, PK_pixfmtNul, PK_PI_NCH, 4, 8, 1}, + {&GUID_PKPixelFormat40bpp5Channels, 5, NCOMPONENT, BD_8, 40, PK_pixfmtNul, PK_PI_NCH, 5, 8, 1}, + {&GUID_PKPixelFormat48bpp6Channels, 6, NCOMPONENT, BD_8, 48, PK_pixfmtNul, PK_PI_NCH, 6, 8, 1}, + {&GUID_PKPixelFormat56bpp7Channels, 7, NCOMPONENT, BD_8, 56, PK_pixfmtNul, PK_PI_NCH, 7, 8, 1}, + {&GUID_PKPixelFormat64bpp8Channels, 8, NCOMPONENT, BD_8, 64, PK_pixfmtNul, PK_PI_NCH, 8, 8, 1}, + + {&GUID_PKPixelFormat32bpp3ChannelsAlpha, 4, NCOMPONENT, BD_8, 32, PK_pixfmtHasAlpha, PK_PI_NCH, 4, 8, 1}, + {&GUID_PKPixelFormat40bpp4ChannelsAlpha, 5, NCOMPONENT, BD_8, 40, PK_pixfmtHasAlpha, PK_PI_NCH, 5, 8, 1}, + {&GUID_PKPixelFormat48bpp5ChannelsAlpha, 6, NCOMPONENT, BD_8, 48, PK_pixfmtHasAlpha, PK_PI_NCH, 6, 8, 1}, + {&GUID_PKPixelFormat56bpp6ChannelsAlpha, 7, NCOMPONENT, BD_8, 56, PK_pixfmtHasAlpha, PK_PI_NCH, 7, 8, 1}, + {&GUID_PKPixelFormat64bpp7ChannelsAlpha, 8, NCOMPONENT, BD_8, 64, PK_pixfmtHasAlpha, PK_PI_NCH, 8, 8, 1}, + {&GUID_PKPixelFormat72bpp8ChannelsAlpha, 9, NCOMPONENT, BD_8, 72, PK_pixfmtHasAlpha, PK_PI_NCH, 9, 8, 1}, + + {&GUID_PKPixelFormat48bpp3Channels, 3, NCOMPONENT, BD_16, 48, PK_pixfmtNul, PK_PI_NCH, 3, 16, 1}, + {&GUID_PKPixelFormat64bpp4Channels, 4, NCOMPONENT, BD_16, 64, PK_pixfmtNul, PK_PI_NCH, 4, 16, 1}, + {&GUID_PKPixelFormat80bpp5Channels, 5, NCOMPONENT, BD_16, 80, PK_pixfmtNul, PK_PI_NCH, 5, 16, 1}, + {&GUID_PKPixelFormat96bpp6Channels, 6, NCOMPONENT, BD_16, 96, PK_pixfmtNul, PK_PI_NCH, 6, 16, 1}, + {&GUID_PKPixelFormat112bpp7Channels, 7, NCOMPONENT, BD_16, 112, PK_pixfmtNul, PK_PI_NCH, 7, 16, 1}, + {&GUID_PKPixelFormat128bpp8Channels, 8, NCOMPONENT, BD_16, 128, PK_pixfmtNul, PK_PI_NCH, 8, 16, 1}, + + {&GUID_PKPixelFormat64bpp3ChannelsAlpha, 4, NCOMPONENT, BD_16, 64, PK_pixfmtHasAlpha, PK_PI_NCH, 4, 16, 1}, + {&GUID_PKPixelFormat80bpp4ChannelsAlpha, 5, NCOMPONENT, BD_16, 80, PK_pixfmtHasAlpha, PK_PI_NCH, 5, 16, 1}, + {&GUID_PKPixelFormat96bpp5ChannelsAlpha, 6, NCOMPONENT, BD_16, 96, PK_pixfmtHasAlpha, PK_PI_NCH, 6, 16, 1}, + {&GUID_PKPixelFormat112bpp6ChannelsAlpha, 7, NCOMPONENT, BD_16, 112, PK_pixfmtHasAlpha, PK_PI_NCH, 7, 16, 1}, + {&GUID_PKPixelFormat128bpp7ChannelsAlpha, 8, NCOMPONENT, BD_16, 128, PK_pixfmtHasAlpha, PK_PI_NCH, 8, 16, 1}, + {&GUID_PKPixelFormat144bpp8ChannelsAlpha, 9, NCOMPONENT, BD_16, 144, PK_pixfmtHasAlpha, PK_PI_NCH, 9, 16, 1}, + + //RGBE + {&GUID_PKPixelFormat32bppRGBE, 4, CF_RGBE, BD_8, 32, PK_pixfmtNul, PK_PI_RGBE, 4, 8, 1}, + + //YUV + {&GUID_PKPixelFormat12bppYUV420, 3, YUV_420, BD_8, 48, PK_pixfmtNul}, + {&GUID_PKPixelFormat16bppYUV422, 3, YUV_422, BD_8, 32, PK_pixfmtNul}, + {&GUID_PKPixelFormat24bppYUV444, 3, YUV_444, BD_8, 24, PK_pixfmtNul}, +}; + +//---------------------------------------------------------------- +//ERR GetPixelInfo(PKPixelFormatGUID enPixelFormat, const PKPixelInfo** ppPI) +ERR PixelFormatLookup(PKPixelInfo* pPI, U8 uLookupType) +{ + ERR err = WMP_errSuccess; + size_t i; + + for (i = 0; i < sizeof2(pixelInfo); ++i) + { + if (LOOKUP_FORWARD == uLookupType) + { + if (IsEqualGUID(pPI->pGUIDPixFmt, pixelInfo[i].pGUIDPixFmt)) + { + *pPI = pixelInfo[i]; + goto Cleanup; + } + } + else if (LOOKUP_BACKWARD_TIF == uLookupType) + { + if (pPI->uSamplePerPixel == pixelInfo[i].uSamplePerPixel && + pPI->uBitsPerSample == pixelInfo[i].uBitsPerSample && + pPI->uSampleFormat == pixelInfo[i].uSampleFormat && + pPI->uInterpretation == pixelInfo[i].uInterpretation) + { + // match alpha & premult + if ((pPI->grBit & (PK_pixfmtHasAlpha | PK_pixfmtPreMul)) == + (pixelInfo[i].grBit & (PK_pixfmtHasAlpha | PK_pixfmtPreMul))) + { + *pPI = pixelInfo[i]; + goto Cleanup; + } + } + } + } + Call(WMP_errUnsupportedFormat); + +Cleanup: + return err; +} + + +const PKPixelFormatGUID* GetPixelFormatFromHash(const U8 uPFHash) +{ + int i; + + for (i = 0; i < sizeof2(pixelInfo); i++) + { + if (pixelInfo[i].pGUIDPixFmt->Data4[7] == uPFHash) + return pixelInfo[i].pGUIDPixFmt; + } + + // If we reached this point, we did not find anything which matched the hash + return NULL; +} + +//---------------------------------------------------------------- +typedef struct tagPKIIDInfo +{ + const char* szExt; + const PKIID* pIIDEnc; + const PKIID* pIIDDec; +} PKIIDInfo; + +static ERR GetIIDInfo(const char* szExt, const PKIIDInfo** ppInfo) +{ + ERR err = WMP_errSuccess; + + static PKIIDInfo iidInfo[] = { + {".jxr", &IID_PKImageWmpEncode, &IID_PKImageWmpDecode}, + {".wdp", &IID_PKImageUnsupported, &IID_PKImageWmpDecode}, + {".hdp", &IID_PKImageUnsupported, &IID_PKImageWmpDecode}, + }; + size_t i = 0; + + *ppInfo = NULL; + for (i = 0; i < sizeof2(iidInfo); ++i) + { + if (0 == PKStrnicmp(szExt, iidInfo[i].szExt, strlen(iidInfo[i].szExt))) + { + *ppInfo = &iidInfo[i]; + goto Cleanup; + } + } + + Call(WMP_errUnsupportedFormat); + +Cleanup: + return err; +} + +ERR GetImageEncodeIID(const char* szExt, const PKIID** ppIID) +{ + ERR err = WMP_errSuccess; + + const PKIIDInfo* pInfo = NULL; + + Call(GetIIDInfo(szExt, &pInfo)); + *ppIID = pInfo->pIIDEnc; + +Cleanup: + return err; +} + +ERR GetImageDecodeIID(const char* szExt, const PKIID** ppIID) +{ + ERR err = WMP_errSuccess; + + const PKIIDInfo* pInfo = NULL; + + Call(GetIIDInfo(szExt, &pInfo)); + *ppIID = pInfo->pIIDDec; + +Cleanup: + return err; +} + +//================================================================ +// PKFactory +//================================================================ +ERR PKCreateFactory_CreateStream(PKStream** ppStream) +{ + ERR err = WMP_errSuccess; + + Call(PKAlloc((void **) ppStream, sizeof(**ppStream))); + +Cleanup: + return err; +} + +ERR PKCreateFactory_Release(PKFactory** ppFactory) +{ + ERR err = WMP_errSuccess; + + Call(PKFree((void **) ppFactory)); + +Cleanup: + return err; +} + +//---------------------------------------------------------------- +ERR PKCreateFactory(PKFactory** ppFactory, U32 uVersion) +{ + ERR err = WMP_errSuccess; + PKFactory* pFactory = NULL; + + UNREFERENCED_PARAMETER( uVersion ); + + Call(PKAlloc((void **) ppFactory, sizeof(**ppFactory))); + pFactory = *ppFactory; + + pFactory->CreateStream = PKCreateFactory_CreateStream; + + pFactory->CreateStreamFromFilename = CreateWS_File; + pFactory->CreateStreamFromMemory = CreateWS_Memory; + + pFactory->Release = PKCreateFactory_Release; + +Cleanup: + return err; +} + + +//================================================================ +// PKCodecFactory +//================================================================ +ERR PKCodecFactory_CreateCodec(const PKIID* iid, void** ppv) +{ + ERR err = WMP_errSuccess; + + if (IID_PKImageWmpEncode == *iid) + { + Call(PKImageEncode_Create_WMP((PKImageEncode**)ppv)); + } + else if (IID_PKImageWmpDecode == *iid) + { + Call(PKImageDecode_Create_WMP((PKImageDecode**)ppv)); + } + else + { + Call(WMP_errUnsupportedFormat); + } + +Cleanup: + return err; +} + +ERR PKCodecFactory_CreateDecoderFromFile(const char* szFilename, PKImageDecode** ppDecoder) +{ + ERR err = WMP_errSuccess; + + char *pExt = NULL; + const PKIID* pIID = NULL; + + struct WMPStream* pStream = NULL; + PKImageDecode* pDecoder = NULL; + + // get file extension + pExt = strrchr(szFilename, '.'); + FailIf(NULL == pExt, WMP_errUnsupportedFormat); + + // get decode PKIID + Call(GetImageDecodeIID(pExt, &pIID)); + + // create stream + Call(CreateWS_File(&pStream, szFilename, "rb")); + + // Create decoder + Call(PKCodecFactory_CreateCodec(pIID, (void **) ppDecoder)); + pDecoder = *ppDecoder; + + // attach stream to decoder + Call(pDecoder->Initialize(pDecoder, pStream)); + pDecoder->fStreamOwner = !0; + +Cleanup: + return err; +} + +ERR PKCodecFactory_CreateFormatConverter(PKFormatConverter** ppFConverter) +{ + ERR err = WMP_errSuccess; + PKFormatConverter* pFC = NULL; + + Call(PKAlloc((void **) ppFConverter, sizeof(**ppFConverter))); + pFC = *ppFConverter; + + pFC->Initialize = PKFormatConverter_Initialize; + pFC->InitializeConvert = PKFormatConverter_InitializeConvert; + pFC->GetPixelFormat = PKFormatConverter_GetPixelFormat; + pFC->GetSourcePixelFormat = PKFormatConverter_GetSourcePixelFormat; + pFC->GetSize = PKFormatConverter_GetSize; + pFC->GetResolution = PKFormatConverter_GetResolution; + pFC->Copy = PKFormatConverter_Copy; + pFC->Convert = PKFormatConverter_Convert; + pFC->Release = PKFormatConverter_Release; + +Cleanup: + return err; +} + +ERR PKCreateCodecFactory_Release(PKCodecFactory** ppCFactory) +{ + ERR err = WMP_errSuccess; + + Call(PKFree((void **) ppCFactory)); + +Cleanup: + return err; +} + +ERR PKCreateCodecFactory(PKCodecFactory** ppCFactory, U32 uVersion) +{ + ERR err = WMP_errSuccess; + PKCodecFactory* pCFactory = NULL; + + UNREFERENCED_PARAMETER( uVersion ); + + Call(PKAlloc((void **) ppCFactory, sizeof(**ppCFactory))); + pCFactory = *ppCFactory; + + pCFactory->CreateCodec = PKCodecFactory_CreateCodec; + pCFactory->CreateDecoderFromFile = PKCodecFactory_CreateDecoderFromFile; + pCFactory->CreateFormatConverter = PKCodecFactory_CreateFormatConverter; + pCFactory->Release = PKCreateCodecFactory_Release; + +Cleanup: + return err; +} + + +//================================================================ +// PKImageEncode +//================================================================ +ERR PKImageEncode_Initialize( + PKImageEncode* pIE, + struct WMPStream* pStream, + void* pvParam, + size_t cbParam) +{ + ERR err = WMP_errSuccess; + + UNREFERENCED_PARAMETER( pIE ); + UNREFERENCED_PARAMETER( pvParam ); + UNREFERENCED_PARAMETER( cbParam ); + + pIE->pStream = pStream; + pIE->guidPixFormat = GUID_PKPixelFormatDontCare; + pIE->fResX = 96; + pIE->fResY = 96; + pIE->cFrame = 1; + + Call(pIE->pStream->GetPos(pIE->pStream, &pIE->offStart)); + +Cleanup: + return err; +} + +ERR PKImageEncode_Terminate( + PKImageEncode* pIE) +{ + UNREFERENCED_PARAMETER( pIE ); + return WMP_errSuccess; +} + +ERR PKImageEncode_SetPixelFormat( + PKImageEncode* pIE, + PKPixelFormatGUID enPixelFormat) +{ + pIE->guidPixFormat = enPixelFormat; + + return WMP_errSuccess; +} + +ERR PKImageEncode_SetSize( + PKImageEncode* pIE, + I32 iWidth, + I32 iHeight) +{ + ERR err = WMP_errSuccess; + + pIE->uWidth = (U32)iWidth; + pIE->uHeight = (U32)iHeight; + + return err; +} + +ERR PKImageEncode_SetResolution( + PKImageEncode* pIE, + Float fResX, + Float fResY) +{ + pIE->fResX = fResX; + pIE->fResY = fResY; + + return WMP_errSuccess; +} + +ERR PKImageEncode_SetColorContext(PKImageEncode *pIE, + const U8 *pbColorContext, + U32 cbColorContext) +{ + UNREFERENCED_PARAMETER( pIE ); + UNREFERENCED_PARAMETER( pbColorContext ); + UNREFERENCED_PARAMETER( cbColorContext ); + return WMP_errNotYetImplemented; +} + + +ERR PKImageEncode_SetDescriptiveMetadata(PKImageEncode *pIE, const DESCRIPTIVEMETADATA *pDescMetadata) +{ + UNREFERENCED_PARAMETER( pIE ); + UNREFERENCED_PARAMETER( pDescMetadata ); + return WMP_errNotYetImplemented; +} + +ERR PKImageEncode_WritePixels( + PKImageEncode* pIE, + U32 cLine, + U8* pbPixels, + U32 cbStride) +{ + UNREFERENCED_PARAMETER( pIE ); + UNREFERENCED_PARAMETER( cLine ); + UNREFERENCED_PARAMETER( pbPixels ); + UNREFERENCED_PARAMETER( cbStride ); + return WMP_errAbstractMethod; +} + +ERR PKImageEncode_WriteSource( + PKImageEncode* pIE, + PKFormatConverter* pFC, + PKRect* pRect) +{ + ERR err = WMP_errSuccess; + + PKPixelFormatGUID enPFFrom = GUID_PKPixelFormatDontCare; + PKPixelFormatGUID enPFTo = GUID_PKPixelFormatDontCare; + + PKPixelInfo pPIFrom; + PKPixelInfo pPITo; + + U32 cbStrideTo = 0; + U32 cbStrideFrom = 0; + U32 cbStride = 0; + + U8* pb = NULL; + + // CWMTranscodingParam* pParam = NULL; + + // get pixel format + Call(pFC->GetSourcePixelFormat(pFC, &enPFFrom)); + Call(pFC->GetPixelFormat(pFC, &enPFTo)); + FailIf(!IsEqualGUID(&pIE->guidPixFormat, &enPFTo), WMP_errUnsupportedFormat); + + // calc common stride +// Call(GetPixelInfo(enPFFrom, &pPIFrom)); + pPIFrom.pGUIDPixFmt = &enPFFrom; + PixelFormatLookup(&pPIFrom, LOOKUP_FORWARD); + +// Call(GetPixelInfo(enPFTo, &pPITo)); + pPITo.pGUIDPixFmt = &enPFTo; + PixelFormatLookup(&pPITo, LOOKUP_FORWARD); + +// cbStrideFrom = (pPIFrom->cbPixel * pRect->Width + pPIFrom->cbPixelDenom - 1) / pPIFrom->cbPixelDenom; + cbStrideFrom = (BD_1 == pPIFrom.bdBitDepth ? ((pPIFrom.cbitUnit * pRect->Width + 7) >> 3) : (((pPIFrom.cbitUnit + 7) >> 3) * pRect->Width)); + if (&GUID_PKPixelFormat12bppYUV420 == pPIFrom.pGUIDPixFmt + || &GUID_PKPixelFormat16bppYUV422 == pPIFrom.pGUIDPixFmt) + cbStrideFrom >>= 1; + +// cbStrideTo = (pPITo->cbPixel * pIE->uWidth + pPITo->cbPixelDenom - 1) / pPITo->cbPixelDenom; + cbStrideTo = (BD_1 == pPITo.bdBitDepth ? ((pPITo.cbitUnit * pIE->uWidth + 7) >> 3) : (((pPITo.cbitUnit + 7) >> 3) * pIE->uWidth)); + if (&GUID_PKPixelFormat12bppYUV420 == pPITo.pGUIDPixFmt + || &GUID_PKPixelFormat16bppYUV422 == pPITo.pGUIDPixFmt) + cbStrideTo >>= 1; + + cbStride = max(cbStrideFrom, cbStrideTo); + + // actual dec/enc with local buffer + Call(PKAllocAligned((void **) &pb, cbStride * pRect->Height, 128)); + + Call(pFC->Copy(pFC, pRect, pb, cbStride)); + + Call(pIE->WritePixels(pIE, pRect->Height, pb, cbStride)); + +Cleanup: + PKFreeAligned((void **) &pb); + return err; +} + +ERR PKImageEncode_WritePixelsBandedBegin(PKImageEncode* pEncoder, struct WMPStream *pPATempFile) +{ + UNREFERENCED_PARAMETER( pEncoder ); + UNREFERENCED_PARAMETER( pPATempFile ); + return WMP_errAbstractMethod; +} + +ERR PKImageEncode_WritePixelsBanded(PKImageEncode* pEncoder, U32 cLines, U8* pbPixels, U32 cbStride, Bool fLastCall) +{ + UNREFERENCED_PARAMETER( pEncoder ); + UNREFERENCED_PARAMETER( cLines ); + UNREFERENCED_PARAMETER( pbPixels ); + UNREFERENCED_PARAMETER( cbStride ); + UNREFERENCED_PARAMETER( fLastCall ); + return WMP_errAbstractMethod; +} + +ERR PKImageEncode_WritePixelsBandedEnd(PKImageEncode* pEncoder) +{ + UNREFERENCED_PARAMETER( pEncoder ); + return WMP_errAbstractMethod; +} + + +ERR PKImageEncode_Transcode( + PKImageEncode* pIE, + PKFormatConverter* pFC, + PKRect* pRect) +{ + ERR err = WMP_errSuccess; + + PKPixelFormatGUID enPFFrom = GUID_PKPixelFormatDontCare; + PKPixelFormatGUID enPFTo = GUID_PKPixelFormatDontCare; + + PKPixelInfo pPIFrom; + PKPixelInfo pPITo; + + U32 cbStrideTo = 0; + U32 cbStrideFrom = 0; + U32 cbStride = 0; + + U8* pb = NULL; + + CWMTranscodingParam cParam = {0}; + + // get pixel format + Call(pFC->GetSourcePixelFormat(pFC, &enPFFrom)); + Call(pFC->GetPixelFormat(pFC, &enPFTo)); + FailIf(!IsEqualGUID(&pIE->guidPixFormat, &enPFTo), WMP_errUnsupportedFormat); + + // calc common stride +// Call(GetPixelInfo(enPFFrom, &pPIFrom)); + pPIFrom.pGUIDPixFmt = &enPFFrom; + PixelFormatLookup(&pPIFrom, LOOKUP_FORWARD); + +// Call(GetPixelInfo(enPFTo, &pPITo)); + pPITo.pGUIDPixFmt = &enPFTo; + PixelFormatLookup(&pPITo, LOOKUP_FORWARD); + +// cbStrideFrom = (pPIFrom->cbPixel * pRect->Width + pPIFrom->cbPixelDenom - 1) / pPIFrom->cbPixelDenom; + cbStrideFrom = (BD_1 == pPIFrom.bdBitDepth ? ((pPIFrom.cbitUnit * pRect->Width + 7) >> 3) : (((pPIFrom.cbitUnit + 7) >> 3) * pRect->Width)); + if (&GUID_PKPixelFormat12bppYUV420 == pPIFrom.pGUIDPixFmt + || &GUID_PKPixelFormat16bppYUV422 == pPIFrom.pGUIDPixFmt) + cbStrideFrom >>= 1; + +// cbStrideTo = (pPITo->cbPixel * pIE->uWidth + pPITo->cbPixelDenom - 1) / pPITo->cbPixelDenom; + cbStrideTo = (BD_1 == pPITo.bdBitDepth ? ((pPITo.cbitUnit * pIE->uWidth + 7) >> 3) : (((pPITo.cbitUnit + 7) >> 3) * pIE->uWidth)); + if (&GUID_PKPixelFormat12bppYUV420 == pPITo.pGUIDPixFmt + || &GUID_PKPixelFormat16bppYUV422 == pPITo.pGUIDPixFmt) + cbStrideTo >>= 1; + + cbStride = max(cbStrideFrom, cbStrideTo); + + if(pIE->bWMP){ + cParam.cLeftX = pFC->pDecoder->WMP.wmiI.cROILeftX; + cParam.cTopY = pFC->pDecoder->WMP.wmiI.cROITopY; + cParam.cWidth = pFC->pDecoder->WMP.wmiI.cROIWidth; + cParam.cHeight = pFC->pDecoder->WMP.wmiI.cROIHeight; + cParam.oOrientation = pFC->pDecoder->WMP.wmiI.oOrientation; +// cParam.cfColorFormat = pFC->pDecoder->WMP.wmiI.cfColorFormat; + cParam.uAlphaMode = pFC->pDecoder->WMP.wmiSCP.uAlphaMode; + cParam.bfBitstreamFormat = pFC->pDecoder->WMP.wmiSCP.bfBitstreamFormat; + cParam.sbSubband = pFC->pDecoder->WMP.wmiSCP.sbSubband; + cParam.bIgnoreOverlap = pFC->pDecoder->WMP.bIgnoreOverlap; + + Call(pIE->Transcode(pIE, pFC->pDecoder, &cParam)); + } + else + { + // actual dec/enc with local buffer + Call(PKAllocAligned((void **) &pb, cbStride * pRect->Height, 128)); + Call(pFC->Copy(pFC, pRect, pb, cbStride)); + Call(pIE->WritePixels(pIE, pRect->Height, pb, cbStride)); + } + +Cleanup: + PKFreeAligned((void **) &pb); + return err; +} + +ERR PKImageEncode_CreateNewFrame( + PKImageEncode* pIE, + void* pvParam, + size_t cbParam) +{ + UNREFERENCED_PARAMETER( pIE ); + UNREFERENCED_PARAMETER( pvParam ); + UNREFERENCED_PARAMETER( cbParam ); + // NYI + return WMP_errSuccess; +} + +ERR PKImageEncode_Release( + PKImageEncode** ppIE) +{ + PKImageEncode *pIE = *ppIE; + pIE->pStream->Close(&pIE->pStream); + + return PKFree((void **) ppIE); +} + +ERR PKImageEncode_Create(PKImageEncode** ppIE) +{ + ERR err = WMP_errSuccess; + PKImageEncode* pIE = NULL; + + Call(PKAlloc((void **) ppIE, sizeof(**ppIE))); + + pIE = *ppIE; + pIE->Initialize = PKImageEncode_Initialize; + pIE->Terminate = PKImageEncode_Terminate; + pIE->SetPixelFormat = PKImageEncode_SetPixelFormat; + pIE->SetSize = PKImageEncode_SetSize; + pIE->SetResolution = PKImageEncode_SetResolution; + pIE->SetColorContext = PKImageEncode_SetColorContext; + pIE->SetDescriptiveMetadata = PKImageEncode_SetDescriptiveMetadata; + pIE->WritePixels = PKImageEncode_WritePixels; +// pIE->WriteSource = PKImageEncode_WriteSource; + + pIE->WritePixelsBandedBegin = PKImageEncode_WritePixelsBandedBegin; + pIE->WritePixelsBanded = PKImageEncode_WritePixelsBanded; + pIE->WritePixelsBandedEnd = PKImageEncode_WritePixelsBandedEnd; + + pIE->CreateNewFrame = PKImageEncode_CreateNewFrame; + pIE->Release = PKImageEncode_Release; + pIE->bWMP = FALSE; + +Cleanup: + return err; +} + + +//================================================================ +// PKImageDecode +//================================================================ +ERR PKImageDecode_Initialize( + PKImageDecode* pID, + struct WMPStream* pStream) +{ + ERR err = WMP_errSuccess; + + pID->pStream = pStream; + pID->guidPixFormat = GUID_PKPixelFormatDontCare; + pID->fResX = 96; + pID->fResY = 96; + pID->cFrame = 1; + + Call(pID->pStream->GetPos(pID->pStream, &pID->offStart)); + + memset(&pID->WMP.wmiDEMisc, 0, sizeof(pID->WMP.wmiDEMisc)); + +Cleanup: + return WMP_errSuccess; +} + +ERR PKImageDecode_GetPixelFormat( + PKImageDecode* pID, + PKPixelFormatGUID* pPF) +{ + *pPF = pID->guidPixFormat; + + return WMP_errSuccess; +} + +ERR PKImageDecode_GetSize( + PKImageDecode* pID, + I32* piWidth, + I32* piHeight) +{ + *piWidth = (I32)pID->uWidth; + *piHeight = (I32)pID->uHeight; + + return WMP_errSuccess; +} + +ERR PKImageDecode_GetResolution( + PKImageDecode* pID, + Float* pfResX, + Float* pfResY) +{ + *pfResX = pID->fResX; + *pfResY = pID->fResY; + + return WMP_errSuccess; +} + +ERR PKImageDecode_GetColorContext(PKImageDecode *pID, U8 *pbColorContext, U32 *pcbColorContext) +{ + UNREFERENCED_PARAMETER( pID ); + UNREFERENCED_PARAMETER( pbColorContext ); + UNREFERENCED_PARAMETER( pcbColorContext ); + return WMP_errNotYetImplemented; +} + +ERR PKImageDecode_GetDescriptiveMetadata(PKImageDecode *pIE, DESCRIPTIVEMETADATA *pDescMetadata) +{ + UNREFERENCED_PARAMETER( pIE ); + UNREFERENCED_PARAMETER( pDescMetadata ); + return WMP_errNotYetImplemented; +} + +ERR PKImageDecode_Copy( + PKImageDecode* pID, + const PKRect* pRect, + U8* pb, + U32 cbStride) +{ + UNREFERENCED_PARAMETER( pID ); + UNREFERENCED_PARAMETER( pRect ); + UNREFERENCED_PARAMETER( pb ); + UNREFERENCED_PARAMETER( cbStride ); + return WMP_errAbstractMethod; +} + +ERR PKImageDecode_GetFrameCount( + PKImageDecode* pID, + U32* puCount) +{ + *puCount = pID->cFrame; + + return WMP_errSuccess; +} + +ERR PKImageDecode_SelectFrame( + PKImageDecode* pID, + U32 uFrame) +{ + UNREFERENCED_PARAMETER( pID ); + UNREFERENCED_PARAMETER( uFrame ); + // NYI + return WMP_errSuccess; +} + +ERR PKImageDecode_Release( + PKImageDecode** ppID) +{ + PKImageDecode* pID = *ppID; + + pID->fStreamOwner && pID->pStream->Close(&pID->pStream); + + return PKFree((void **) ppID); +} + +ERR PKImageDecode_Create( + PKImageDecode** ppID) +{ + ERR err = WMP_errSuccess; + PKImageDecode* pID = NULL; + + Call(PKAlloc((void **) ppID, sizeof(**ppID))); + + pID = *ppID; + pID->Initialize = PKImageDecode_Initialize; + pID->GetPixelFormat = PKImageDecode_GetPixelFormat; + pID->GetSize = PKImageDecode_GetSize; + pID->GetResolution = PKImageDecode_GetResolution; + pID->GetColorContext = PKImageDecode_GetColorContext; + pID->GetDescriptiveMetadata = PKImageDecode_GetDescriptiveMetadata; + pID->Copy = PKImageDecode_Copy; + pID->GetFrameCount = PKImageDecode_GetFrameCount; + pID->SelectFrame = PKImageDecode_SelectFrame; + pID->Release = PKImageDecode_Release; + +Cleanup: + return err; +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.h new file mode 100644 index 0000000..49e69c3 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.h @@ -0,0 +1,642 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +//================================================================ +#define WMP_SDK_VERSION 0x0101 +#define PK_SDK_VERSION 0x0101 + +#define sizeof2(array) (sizeof(array)/sizeof(*(array))) +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef min +#define min(b,a) ((a) < (b) ? (a) : (b)) +#endif +#ifdef __ANSI__ +#define STRCPY_SAFE(pszDest, cbDest, pszSrc) (strncpy((pszDest), (pszSrc), (cbDest)) == (pszDest) ? 0 : 1) +#else +#define STRCPY_SAFE(pszDest, cbDest, pszSrc) (strcpy_s((pszDest), (cbDest), (pszSrc))) +#endif // __ANSI__ + +//================================================================ +typedef struct tagPKRect +{ + I32 X; + I32 Y; + I32 Width; + I32 Height; +} PKRect; + +//================================================================ +typedef U32 PKIID; + +EXTERN_C const PKIID IID_PKImageScanEncode; +EXTERN_C const PKIID IID_PKImageFrameEncode; + +EXTERN_C const PKIID IID_PKImageWmpEncode; + +EXTERN_C const PKIID IID_PKImageWmpDecode; + +struct IFDEntry +{ + U16 uTag; + U16 uType; + U32 uCount; + U32 uValue; +}; +EXTERN_C const U32 IFDEntryTypeSizes[13]; +EXTERN_C const U32 SizeofIFDEntry; + +//================================================================ +typedef float Float; + +typedef enum tagPKStreamFlags +{ + PKStreamOpenRead = 0x00000000UL, + PKStreamOpenWrite = 0x00000001UL, + PKStreamOpenReadWrite = 0x00000002UL, + PKStreamNoLock = 0x00010000UL, + PKStreamNoSeek = 0x00020000UL, + PKStreamCompress = 0x00040000UL, +} PKStreamFlags; + +/* Undefined formats */ +#define GUID_PKPixelFormatUndefined GUID_PKPixelFormatDontCare + +DEFINE_GUID(GUID_PKPixelFormatDontCare, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x00); + +/* Indexed formats */ +//DEFINE_GUID(GUID_PKPixelFormat1bppIndexed, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x01); +//DEFINE_GUID(GUID_PKPixelFormat2bppIndexed, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x02); +//DEFINE_GUID(GUID_PKPixelFormat4bppIndexed, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x03); +//DEFINE_GUID(GUID_PKPixelFormat8bppIndexed, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x04); + +DEFINE_GUID(GUID_PKPixelFormatBlackWhite, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x05); +//DEFINE_GUID(GUID_PKPixelFormat2bppGray, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x06); +//DEFINE_GUID(GUID_PKPixelFormat4bppGray, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x07); +DEFINE_GUID(GUID_PKPixelFormat8bppGray, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x08); + +/* sRGB formats (gamma is approx. 2.2) */ +/* For a full definition, see the sRGB spec */ + +/* 16bpp formats */ +DEFINE_GUID(GUID_PKPixelFormat16bppRGB555, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x09); +DEFINE_GUID(GUID_PKPixelFormat16bppRGB565, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0a); +DEFINE_GUID(GUID_PKPixelFormat16bppGray, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0b); + +/* 24bpp formats */ +DEFINE_GUID(GUID_PKPixelFormat24bppBGR, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c); +DEFINE_GUID(GUID_PKPixelFormat24bppRGB, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d); + +/* 32bpp format */ +DEFINE_GUID(GUID_PKPixelFormat32bppBGR, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0e); +DEFINE_GUID(GUID_PKPixelFormat32bppBGRA, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f); +DEFINE_GUID(GUID_PKPixelFormat32bppPBGRA, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x10); +DEFINE_GUID(GUID_PKPixelFormat32bppGrayFloat, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x11); +DEFINE_GUID(GUID_PKPixelFormat32bppRGB, 0xd98c6b95, 0x3efe, 0x47d6, 0xbb, 0x25, 0xeb, 0x17, 0x48, 0xab, 0x0c, 0xf1); +DEFINE_GUID(GUID_PKPixelFormat32bppRGBA, 0xf5c7ad2d, 0x6a8d, 0x43dd, 0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9); +DEFINE_GUID(GUID_PKPixelFormat32bppPRGBA, 0x3cc4a650, 0xa527, 0x4d37, 0xa9, 0x16, 0x31, 0x42, 0xc7, 0xeb, 0xed, 0xba); + +/* 48bpp format */ +DEFINE_GUID(GUID_PKPixelFormat48bppRGBFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x12); + +/* scRGB formats. Gamma is 1.0 */ +/* For a full definition, see the scRGB spec */ + +/* 16bpp format */ +DEFINE_GUID(GUID_PKPixelFormat16bppGrayFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x13); + +/* 32bpp format */ +DEFINE_GUID(GUID_PKPixelFormat32bppRGB101010, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x14); + +/* 48bpp format */ +DEFINE_GUID(GUID_PKPixelFormat48bppRGB, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x15); + +/* 64bpp format */ +DEFINE_GUID(GUID_PKPixelFormat64bppRGBA, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x16); +DEFINE_GUID(GUID_PKPixelFormat64bppPRGBA, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x17); + +/* 96bpp format */ +DEFINE_GUID(GUID_PKPixelFormat96bppRGBFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x18); +DEFINE_GUID(GUID_PKPixelFormat96bppRGBFloat, 0xe3fed78f, 0xe8db, 0x4acf, 0x84, 0xc1, 0xe9, 0x7f, 0x61, 0x36, 0xb3, 0x27); + + /* Floating point scRGB formats */ +DEFINE_GUID(GUID_PKPixelFormat128bppRGBAFloat, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x19); +DEFINE_GUID(GUID_PKPixelFormat128bppPRGBAFloat, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1a); +DEFINE_GUID(GUID_PKPixelFormat128bppRGBFloat, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1b); + + /* CMYK formats. */ +DEFINE_GUID(GUID_PKPixelFormat32bppCMYK, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1c); + + /* Photon formats */ +DEFINE_GUID(GUID_PKPixelFormat64bppRGBAFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1d); +DEFINE_GUID(GUID_PKPixelFormat64bppRGBFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x40); +DEFINE_GUID(GUID_PKPixelFormat128bppRGBAFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1e); +DEFINE_GUID(GUID_PKPixelFormat128bppRGBFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x41); + +DEFINE_GUID(GUID_PKPixelFormat64bppRGBAHalf, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3a); +DEFINE_GUID(GUID_PKPixelFormat64bppRGBHalf, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x42); +DEFINE_GUID(GUID_PKPixelFormat48bppRGBHalf, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3b); + +DEFINE_GUID(GUID_PKPixelFormat32bppRGBE, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3d); + +DEFINE_GUID(GUID_PKPixelFormat16bppGrayHalf, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3e); +DEFINE_GUID(GUID_PKPixelFormat32bppGrayFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3f); + + +/* More CMYK formats and n-Channel formats */ +DEFINE_GUID(GUID_PKPixelFormat64bppCMYK, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1f); + +DEFINE_GUID(GUID_PKPixelFormat24bpp3Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x20); +DEFINE_GUID(GUID_PKPixelFormat32bpp4Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x21); +DEFINE_GUID(GUID_PKPixelFormat40bpp5Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x22); +DEFINE_GUID(GUID_PKPixelFormat48bpp6Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x23); +DEFINE_GUID(GUID_PKPixelFormat56bpp7Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x24); +DEFINE_GUID(GUID_PKPixelFormat64bpp8Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x25); + +DEFINE_GUID(GUID_PKPixelFormat48bpp3Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x26); +DEFINE_GUID(GUID_PKPixelFormat64bpp4Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x27); +DEFINE_GUID(GUID_PKPixelFormat80bpp5Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x28); +DEFINE_GUID(GUID_PKPixelFormat96bpp6Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x29); +DEFINE_GUID(GUID_PKPixelFormat112bpp7Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2a); +DEFINE_GUID(GUID_PKPixelFormat128bpp8Channels, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2b); + +DEFINE_GUID(GUID_PKPixelFormat40bppCMYKAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2c); +DEFINE_GUID(GUID_PKPixelFormat80bppCMYKAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2d); + +DEFINE_GUID(GUID_PKPixelFormat32bpp3ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2e); +DEFINE_GUID(GUID_PKPixelFormat40bpp4ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2f); +DEFINE_GUID(GUID_PKPixelFormat48bpp5ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x30); +DEFINE_GUID(GUID_PKPixelFormat56bpp6ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x31); +DEFINE_GUID(GUID_PKPixelFormat64bpp7ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x32); +DEFINE_GUID(GUID_PKPixelFormat72bpp8ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x33); + +DEFINE_GUID(GUID_PKPixelFormat64bpp3ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x34); +DEFINE_GUID(GUID_PKPixelFormat80bpp4ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x35); +DEFINE_GUID(GUID_PKPixelFormat96bpp5ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x36); +DEFINE_GUID(GUID_PKPixelFormat112bpp6ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x37); +DEFINE_GUID(GUID_PKPixelFormat128bpp7ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x38); +DEFINE_GUID(GUID_PKPixelFormat144bpp8ChannelsAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x39); + +/* YCrCb from Advanced Profile */ +DEFINE_GUID(GUID_PKPixelFormat12bppYCC420, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x44); +DEFINE_GUID(GUID_PKPixelFormat16bppYCC422, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x45); +DEFINE_GUID(GUID_PKPixelFormat20bppYCC422, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x46); +DEFINE_GUID(GUID_PKPixelFormat32bppYCC422, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x47); +DEFINE_GUID(GUID_PKPixelFormat24bppYCC444, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x48); +DEFINE_GUID(GUID_PKPixelFormat30bppYCC444, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x49); +DEFINE_GUID(GUID_PKPixelFormat48bppYCC444, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x4a); +DEFINE_GUID(GUID_PKPixelFormat16bpp48bppYCC444FixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x4b); +DEFINE_GUID(GUID_PKPixelFormat20bppYCC420Alpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x4c); +DEFINE_GUID(GUID_PKPixelFormat24bppYCC422Alpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x4d); +DEFINE_GUID(GUID_PKPixelFormat30bppYCC422Alpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x4e); +DEFINE_GUID(GUID_PKPixelFormat48bppYCC422Alpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x4f); +DEFINE_GUID(GUID_PKPixelFormat32bppYCC444Alpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x50); +DEFINE_GUID(GUID_PKPixelFormat40bppYCC444Alpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x51); +DEFINE_GUID(GUID_PKPixelFormat64bppYCC444Alpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x52); +DEFINE_GUID(GUID_PKPixelFormat64bppYCC444AlphaFixedPoint, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x53); + +//YUV +#define GUID_PKPixelFormat12bppYUV420 GUID_PKPixelFormat12bppYCC420 +#define GUID_PKPixelFormat16bppYUV422 GUID_PKPixelFormat16bppYCC422 +#define GUID_PKPixelFormat24bppYUV444 GUID_PKPixelFormat24bppYCC444 + +/* CMYKDIRECT from Advanced Profile */ +DEFINE_GUID(GUID_PKPixelFormat32bppCMYKDIRECT, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x54); +DEFINE_GUID(GUID_PKPixelFormat64bppCMYKDIRECT, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x55); +DEFINE_GUID(GUID_PKPixelFormat40bppCMYKDIRECTAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x56); +DEFINE_GUID(GUID_PKPixelFormat80bppCMYKDIRECTAlpha, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x43); + +// PhotometricInterpretation +#define PK_PI_W0 0 // WhiteIsZero +#define PK_PI_B0 1 // BlackIsZero +#define PK_PI_RGB 2 +#define PK_PI_RGBPalette 3 +#define PK_PI_TransparencyMask 4 +#define PK_PI_CMYK 5 +#define PK_PI_YCbCr 6 +#define PK_PI_CIELab 8 + +#define PK_PI_NCH 100 +#define PK_PI_RGBE 101 + +#define PK_pixfmtNul 0x00000000 +#define PK_pixfmtHasAlpha 0x00000010 +#define PK_pixfmtPreMul 0x00000020 +#define PK_pixfmtBGR 0x00000040 +#define PK_pixfmtNeedConvert 0x80000000 + +#define LOOKUP_FORWARD 0 +#define LOOKUP_BACKWARD_TIF 1 + +typedef unsigned long WMP_GRBIT; +typedef GUID PKPixelFormatGUID; + +typedef struct tagPKPixelInfo +{ + const PKPixelFormatGUID* pGUIDPixFmt; + + size_t cChannel; + COLORFORMAT cfColorFormat; + BITDEPTH_BITS bdBitDepth; + U32 cbitUnit; + + WMP_GRBIT grBit; + + // TIFF + U32 uInterpretation; + U32 uSamplePerPixel; + U32 uBitsPerSample; + U32 uSampleFormat; +} PKPixelInfo; + +//================================================================ +ERR PKAlloc(void** ppv, size_t cb); +ERR PKFree(void** ppv); + +//---------------------------------------------------------------- +//ERR GetPixelInfo(PKPixelFormatGUID enPixelFormat, const PKPixelInfo** ppPI); +ERR PixelFormatLookup(PKPixelInfo* pPI, U8 uLookupType); +const PKPixelFormatGUID* GetPixelFormatFromHash(const U8 uPFHash); + +ERR GetImageEncodeIID(const char* szExt, const PKIID** ppIID); +ERR GetImageDecodeIID(const char* szExt, const PKIID** ppIID); + + +//================================================================ +#ifdef __ANSI__ +struct tagPKFactory; +struct tagPKCodecFactory; +struct tagPKImageDecode; +struct tagPKImageEncode; +struct tagPKFormatConverter; +#define PKFactory struct tagPKFactory +#define PKCodecFactory struct tagPKCodecFactory +#define PKImageDecode struct tagPKImageDecode +#define PKImageEncode struct tagPKImageEncode +#define PKFormatConverter struct tagPKFormatConverter +#else // __ANSI__ +typedef struct tagPKFactory PKFactory; +typedef struct tagPKCodecFactory PKCodecFactory; +typedef struct tagPKImageDecode PKImageDecode; +typedef struct tagPKImageEncode PKImageEncode; +typedef struct tagPKFormatConverter PKFormatConverter; +#endif // __ANSI__ +//================================================================ +typedef struct tagPKStream +{ + ERR (*InitializeFromFilename)(const char*, ULong); + + ERR (*Release)(void); + + FILE* fp; +} PKStream; + + +//================================================================ +typedef struct tagPKFactory +{ + ERR (*CreateStream)(PKStream**); + + ERR (*CreateStreamFromFilename)(struct WMPStream**, const char*, const char*); + ERR (*CreateStreamFromMemory)(struct WMPStream**, void*, size_t); + + ERR (*Release)(PKFactory**); +#ifdef __ANSI__ +#undef PKFactory +#endif // __ANSI__ +} PKFactory; + +//---------------------------------------------------------------- +ERR PKCreateFactory_CreateStream(PKStream** ppStream); +ERR PKCreateFactory_Release(PKFactory** ppFactory); + +EXTERN_C ERR PKCreateFactory(PKFactory**, U32); + + +//================================================================ +typedef struct tagPKCodecFactory +{ + ERR (*CreateCodec)(const PKIID*, void**); + ERR (*CreateDecoderFromFile)(const char*, PKImageDecode**); + ERR (*CreateFormatConverter)(PKFormatConverter**); + + ERR (*Release)(PKCodecFactory**); +#ifdef __ANSI__ +#undef PKCodecFactory +#endif // __ANSI__ +} PKCodecFactory; + +//---------------------------------------------------------------- +ERR PKCodecFactory_CreateCodec(const PKIID* iid, void** ppv); +ERR PKCreateCodecFactory_Release(PKCodecFactory** ppCFactory); + +EXTERN_C ERR PKCreateCodecFactory(PKCodecFactory**, U32); + +//================================================================ + +typedef enum BANDEDENCSTATE +{ + BANDEDENCSTATE_UNINITIALIZED = 0, + BANDEDENCSTATE_INIT, + BANDEDENCSTATE_ENCODING, + BANDEDENCSTATE_TERMINATED, + BANDEDENCSTATE_NONBANDEDENCODE, +} BANDEDENCSTATE; + +typedef struct tagPKImageEncode +{ + //ERR (*GetPixelFormat)(MILPixelFormat*)); + ERR (*Initialize)(PKImageEncode*, struct WMPStream*, void*, size_t); + ERR (*Terminate)(PKImageEncode*); + + ERR (*SetPixelFormat)(PKImageEncode*, PKPixelFormatGUID); + ERR (*SetSize)(PKImageEncode*, I32, I32); + ERR (*SetResolution)(PKImageEncode*, Float, Float); + ERR (*SetColorContext)(PKImageEncode *pIE, const U8 *pbColorContext, + U32 cbColorContext); + ERR (*SetDescriptiveMetadata)(PKImageEncode *pIE, + const DESCRIPTIVEMETADATA *pDescMetadata); + + ERR (*WritePixels)(PKImageEncode*, U32, U8*, U32); + ERR (*WriteSource)(PKImageEncode*, PKFormatConverter*, PKRect*); + + // Banded encode API - currently only implemented for WMP encoder + ERR (*WritePixelsBandedBegin)(PKImageEncode* pEncoder, struct WMPStream *pPlanarAlphaTempFile); + ERR (*WritePixelsBanded)(PKImageEncode* pEncoder, U32 cLines, U8* pbPixels, U32 cbStride, Bool fLastCall); + ERR (*WritePixelsBandedEnd)(PKImageEncode* pEncoder); +#define TEMPFILE_COPYBUF_SIZE 8192 // Means when using tempfile for planar alpha banded encode, copy this many bytes at a time + + ERR (*Transcode)(PKImageEncode*, PKImageDecode*, CWMTranscodingParam*); + + ERR (*CreateNewFrame)(PKImageEncode*, void*, size_t); + + ERR (*Release)(PKImageEncode**); + + struct WMPStream* pStream; + size_t offStart; + + PKPixelFormatGUID guidPixFormat; + + U32 uWidth; + U32 uHeight; + U32 idxCurrentLine; + + Float fResX; + Float fResY; + + U32 cFrame; + + Bool fHeaderDone; + size_t offPixel; + size_t cbPixel; + U8 *pbColorContext; + U32 cbColorContext; + U8 *pbEXIFMetadata; + U32 cbEXIFMetadataByteCount; + U8 *pbGPSInfoMetadata; + U32 cbGPSInfoMetadataByteCount; + U8 *pbIPTCNAAMetadata; + U32 cbIPTCNAAMetadataByteCount; + U8 *pbXMPMetadata; + U32 cbXMPMetadataByteCount; + U8 *pbPhotoshopMetadata; + U32 cbPhotoshopMetadataByteCount; + DESCRIPTIVEMETADATA sDescMetadata; + + Bool bWMP;//for the encoder in decoding + + struct + { + WmpDEMisc wmiDEMisc; + CWMImageInfo wmiI; + CWMIStrCodecParam wmiSCP; + CTXSTRCODEC ctxSC; + CWMImageInfo wmiI_Alpha; + CWMIStrCodecParam wmiSCP_Alpha; + CTXSTRCODEC ctxSC_Alpha; + + Bool bHasAlpha; + Long nOffImage; + Long nCbImage; + Long nOffAlpha; + Long nCbAlpha; + + ORIENTATION oOrientation; + + // Banded encode state variables + BANDEDENCSTATE eBandedEncState; + struct WMPStream *pPATempFile; + } WMP; + +#ifdef __ANSI__ +#undef PKImageEncode +#endif // __ANSI__ +} PKImageEncode; + +//---------------------------------------------------------------- +ERR PKImageEncode_Create_WMP(PKImageEncode** ppIE); + +ERR PKImageEncode_Initialize(PKImageEncode* pIE, struct WMPStream* pStream, void* pvParam, size_t cbParam); +ERR PKImageEncode_Terminate(PKImageEncode* pIE); +ERR PKImageEncode_SetPixelFormat(PKImageEncode* pIE, PKPixelFormatGUID enPixelFormat); +ERR PKImageEncode_SetSize(PKImageEncode* pIE, I32 iWidth, I32 iHeight); +ERR PKImageEncode_SetResolution(PKImageEncode* pIE, Float rX, Float rY); +ERR PKImageEncode_SetColorContext(PKImageEncode *pIE, const U8 *pbColorContext, U32 cbColorContext); +ERR PKImageEncode_SetDescriptiveMetadata(PKImageEncode *pIE, const DESCRIPTIVEMETADATA *pDescMetadata); +ERR PKImageEncode_WritePixels(PKImageEncode* pIE, U32 cLine, U8* pbPixel, U32 cbStride); +ERR PKImageEncode_CreateNewFrame(PKImageEncode* pIE, void* pvParam, size_t cbParam); +ERR PKImageEncode_Release(PKImageEncode** ppIE); + +ERR PKImageEncode_SetXMPMetadata_WMP(PKImageEncode *pIE, const U8 *pbXMPMetadata, U32 cbXMPMetadata); +ERR PKImageEncode_SetEXIFMetadata_WMP(PKImageEncode *pIE, const U8 *pbEXIFMetadata, U32 cbEXIFMetadata); +ERR PKImageEncode_SetGPSInfoMetadata_WMP(PKImageEncode *pIE, const U8 *pbGPSInfoMetadata, U32 cbGPSInfoMetadata); +ERR PKImageEncode_SetIPTCNAAMetadata_WMP(PKImageEncode *pIE, const U8 *pbIPTCNAAMetadata, U32 cbIPTCNAAMetadata); +ERR PKImageEncode_SetPhotoshopMetadata_WMP(PKImageEncode *pIE, const U8 *pbPhotoshopMetadata, U32 cbPhotoshopMetadata); + +void FreeDescMetadata(DPKPROPVARIANT *pvar); + +ERR PKImageEncode_Create(PKImageEncode** ppIE); + +//================================================================ +typedef struct tagPKImageDecode +{ + ERR (*Initialize)(PKImageDecode*, struct WMPStream* pStream); + + ERR (*GetPixelFormat)(PKImageDecode*, PKPixelFormatGUID*); + ERR (*GetSize)(PKImageDecode*, I32*, I32*); + ERR (*GetResolution)(PKImageDecode*, Float*, Float*); + ERR (*GetColorContext)(PKImageDecode *pID, U8 *pbColorContext, + U32 *pcbColorContext); + ERR (*GetDescriptiveMetadata)(PKImageDecode *pIE, + DESCRIPTIVEMETADATA *pDescMetadata); + + ERR (*GetRawStream)(PKImageDecode*, struct WMPStream**); + + ERR (*Copy)(PKImageDecode*, const PKRect*, U8*, U32); + + ERR (*GetFrameCount)(PKImageDecode*, U32*); + ERR (*SelectFrame)(PKImageDecode*, U32); + + ERR (*Release)(PKImageDecode**); + + struct WMPStream* pStream; + Bool fStreamOwner; + size_t offStart; + + PKPixelFormatGUID guidPixFormat; + + U32 uWidth; + U32 uHeight; + U32 idxCurrentLine; + + Float fResX; + Float fResY; + + U32 cFrame; + + struct + { + WmpDEMisc wmiDEMisc; + CWMImageInfo wmiI; + CWMIStrCodecParam wmiSCP; + CTXSTRCODEC ctxSC; + CWMImageInfo wmiI_Alpha; + CWMIStrCodecParam wmiSCP_Alpha; + CTXSTRCODEC ctxSC_Alpha; + + Bool bHasAlpha; + Long nOffImage; + Long nCbImage; + Long nOffAlpha; + Long nCbAlpha; + Bool bIgnoreOverlap; + size_t DecoderCurrMBRow; + size_t DecoderCurrAlphaMBRow; + size_t cMarker; + size_t cLinesDecoded; + size_t cLinesCropped; // Lines may be cropped from the top - buffer for subsequent decodes must be adjusted + Bool fFirstNonZeroDecode; + + Bool fOrientationFromContainer; + ORIENTATION oOrientationFromContainer; // Tag 0xBC02 in HD Photo container + + DESCRIPTIVEMETADATA sDescMetadata; + } WMP; + +#ifdef __ANSI__ +#undef PKImageDecode +#endif // __ANSI__ +} PKImageDecode; + +//---------------------------------------------------------------- +ERR PKImageDecode_Create_WMP(PKImageDecode** ppID); + +ERR PKImageDecode_Initialize(PKImageDecode* pID, struct WMPStream* pStream); +ERR PKImageDecode_GetPixelFormat(PKImageDecode* pID, PKPixelFormatGUID* pPF); +ERR PKImageDecode_GetSize(PKImageDecode* pID, I32* piWidth, I32* piHeight); +ERR PKImageDecode_GetResolution(PKImageDecode* pID, Float* pfrX, Float* pfrY); +ERR PKImageDecode_GetColorContext(PKImageDecode *pID, U8 *pbColorContext, U32 *pcbColorContext); +ERR PKImageDecode_GetDescriptiveMetadata(PKImageDecode *pID, DESCRIPTIVEMETADATA *pDescMetadata); +ERR PKImageDecode_Copy(PKImageDecode* pID, const PKRect* pRect, U8* pb, U32 cbStride); +ERR PKImageDecode_GetFrameCount(PKImageDecode* pID, U32* puCount); +ERR PKImageDecode_SelectFrame(PKImageDecode* pID, U32 uFrame); +ERR PKImageDecode_Release(PKImageDecode** ppID); + +ERR PKImageDecode_GetXMPMetadata_WMP(PKImageDecode *pID, U8 *pbXMPMetadata, U32 *pcbXMPMetadata); +ERR PKImageDecode_GetEXIFMetadata_WMP(PKImageDecode *pID, U8 *pbEXIFMetadata, U32 *pcbEXIFMetadata); +ERR PKImageDecode_GetGPSInfoMetadata_WMP(PKImageDecode *pID, U8 *pbGPSInfoMetadata, U32 *pcbGPSInfoMetadata); +ERR PKImageDecode_GetIPTCNAAMetadata_WMP(PKImageDecode *pID, U8 *pbIPTCNAAMetadata, U32 *pcbIPTCNAAMetadata); +ERR PKImageDecode_GetPhotoshopMetadata_WMP(PKImageDecode *pID, U8 *pbPhotoshopMetadata, U32 *pcbPhotoshopMetadata); + +ERR PKImageDecode_Create(PKImageDecode** ppID); +ERR PKCodecFactory_CreateDecoderFromFile(const char* szFilename, PKImageDecode** ppDecoder); + +//================================================================ +typedef struct tagPKFormatConverter +{ + ERR (*Initialize)(PKFormatConverter*, PKImageDecode*, char *pExt, PKPixelFormatGUID); + ERR (*InitializeConvert)(PKFormatConverter* pFC, const PKPixelFormatGUID enPFFrom, + char *pExt, PKPixelFormatGUID enPFTTo); + + ERR (*GetPixelFormat)(PKFormatConverter*, PKPixelFormatGUID*); + ERR (*GetSourcePixelFormat)(PKFormatConverter*, PKPixelFormatGUID*); + ERR (*GetSize)(PKFormatConverter*, I32*, I32*); + ERR (*GetResolution)(PKFormatConverter*, Float*, Float*); + + ERR (*Copy)(PKFormatConverter*, const PKRect*, U8*, U32); + ERR (*Convert)(PKFormatConverter*, const PKRect*, U8*, U32); + + ERR (*Release)(PKFormatConverter**); + + PKImageDecode* pDecoder; + PKPixelFormatGUID enPixelFormat; +#ifdef __ANSI__ +#undef PKFormatConverter +#endif // __ANSI__ +} PKFormatConverter; + +//---------------------------------------------------------------- +ERR PKImageEncode_Transcode(PKImageEncode* pIE, PKFormatConverter* pFC, PKRect* pRect); +ERR PKImageEncode_WriteSource(PKImageEncode* pIE, PKFormatConverter* pFC, PKRect* pRect); +ERR PKFormatConverter_Initialize(PKFormatConverter* pFC, PKImageDecode* pID, char *pExt, PKPixelFormatGUID enPF); +ERR PKFormatConverter_InitializeConvert(PKFormatConverter* pFC, const PKPixelFormatGUID enPFFrom, + char *pExt, PKPixelFormatGUID enPFTo); +ERR PKFormatConverter_GetPixelFormat(PKFormatConverter* pFC, PKPixelFormatGUID* pPF); +ERR PKFormatConverter_GetSourcePixelFormat(PKFormatConverter* pFC, PKPixelFormatGUID* pPF); +ERR PKFormatConverter_GetSize(PKFormatConverter* pFC, I32* piWidth, I32* piHeight); +ERR PKFormatConverter_GetResolution(PKFormatConverter* pFC, Float* pfrX, Float* pfrY); +ERR PKFormatConverter_Copy(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride); +ERR PKFormatConverter_Convert(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride); +ERR PKFormatConverter_Release(PKFormatConverter** ppFC); + +// Think of this as static member of PKFormatConverter "class" +ERR PKFormatConverter_EnumConversions(const PKPixelFormatGUID *pguidSourcePF, + const U32 iIndex, + const PKPixelFormatGUID **ppguidTargetPF); + +ERR PKCodecFactory_CreateFormatConverter(PKFormatConverter** ppFConverter); + +//---------------------------------------------------------------- +ERR PKAlloc(void** ppv, size_t cb); +ERR PKFree(void** ppv); +ERR PKAllocAligned(void** ppv, size_t cb, size_t iAlign); +ERR PKFreeAligned(void** ppv); + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.o new file mode 100644 index 0000000..1f2b518 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlue.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlueJxr.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlueJxr.c new file mode 100644 index 0000000..a1472c5 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlueJxr.c @@ -0,0 +1,2284 @@ + +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include +#include +#include + + +static const char szHDPhotoFormat[] = "image/vnd.ms-photo"; +const U32 IFDEntryTypeSizes[] = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 }; +const U32 SizeofIFDEntry = sizeof(struct IFDEntry); + + +void CalcMetadataSizeLPSTR(const DPKPROPVARIANT var, + U16 *pcInactiveMetadata, + U32 *pcbOffsetSize, + U32 *pcbCount) +{ + if (DPKVT_EMPTY != var.vt) + { + U32 uiLenWithNull = (U32)strlen(var.VT.pszVal) + 1; // +1 for NULL; + assert(DPKVT_LPSTR == var.vt); + + // We only use offset if size > 4 + if (uiLenWithNull > 4) + *pcbOffsetSize += uiLenWithNull; + + if (pcbCount) + *pcbCount = uiLenWithNull; + } + else + *pcInactiveMetadata += 1; +} + +void CalcMetadataSizeLPWSTR(const DPKPROPVARIANT var, + U16 *pcInactiveMetadata, + U32 *pcbOffsetSize, + U32 *pcbCount) +{ + if (DPKVT_EMPTY != var.vt) + { + U32 uiCBWithNull = sizeof(U16) * ((U32)wcslen((wchar_t *) var.VT.pwszVal) + 1); // +1 for NULL term; + assert(DPKVT_LPWSTR == var.vt); + + // We only use offset if size > 4 + if (uiCBWithNull > 4) + *pcbOffsetSize += uiCBWithNull; + + if (pcbCount) + *pcbCount = uiCBWithNull; + } + else + *pcInactiveMetadata += 1; +} + +void CalcMetadataSizeUI2(const DPKPROPVARIANT var, + U16 *pcInactiveMetadata, + U32 *pcbMetadataSize) +{ + UNREFERENCED_PARAMETER( pcbMetadataSize ); + if (DPKVT_EMPTY != var.vt) + { + assert(DPKVT_UI2 == var.vt); + // This is a single UI2, so it will not be written via offset, but rather as value + } + else + *pcInactiveMetadata += 1; +} + +void CalcMetadataSizeUI4(const DPKPROPVARIANT var, + U16 *pcInactiveMetadata, + U32 *pcbContainer) +{ + UNREFERENCED_PARAMETER( pcbContainer ); + if (DPKVT_EMPTY != var.vt) + { + assert(DPKVT_UI4 == var.vt); + // This is a single UI4, so it will not be written via offset, but rather as value + } + else + *pcInactiveMetadata += 1; +} + +ERR CalcMetadataOffsetSize(PKImageEncode* pIE, + U16 *pcInactiveMetadata, + U32 *pcbMetadataSize) +{ + ERR err = WMP_errSuccess; + + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarImageDescription, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarCameraMake, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarCameraModel, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarSoftware, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarDateTime, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarArtist, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarCopyright, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeUI2(pIE->sDescMetadata.pvarRatingStars, pcInactiveMetadata, pcbMetadataSize); + CalcMetadataSizeUI2(pIE->sDescMetadata.pvarRatingValue, pcInactiveMetadata, pcbMetadataSize); + CalcMetadataSizeLPWSTR(pIE->sDescMetadata.pvarCaption, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarDocumentName, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarPageName, pcInactiveMetadata, pcbMetadataSize, NULL); + CalcMetadataSizeUI4(pIE->sDescMetadata.pvarPageNumber, pcInactiveMetadata, pcbMetadataSize); + CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarHostComputer, pcInactiveMetadata, pcbMetadataSize, NULL); + + return err; +} + + +ERR CopyDescMetadata(DPKPROPVARIANT *pvarDst, + const DPKPROPVARIANT varSrc) +{ + ERR err = WMP_errSuccess; + size_t uiSize; + + pvarDst->vt = varSrc.vt; + switch (varSrc.vt) + { + case DPKVT_LPSTR: + pvarDst->vt = DPKVT_LPSTR; + uiSize = strlen(varSrc.VT.pszVal) + 1; + Call(PKAlloc((void **) &pvarDst->VT.pszVal, uiSize)); + memcpy(pvarDst->VT.pszVal, varSrc.VT.pszVal, uiSize); + break; + + case DPKVT_LPWSTR: + pvarDst->vt = DPKVT_LPWSTR; + uiSize = sizeof(U16) * (wcslen((wchar_t *) varSrc.VT.pwszVal) + 1); // +1 for NULL term + Call(PKAlloc((void **) &pvarDst->VT.pszVal, uiSize)); + memcpy(pvarDst->VT.pwszVal, varSrc.VT.pwszVal, uiSize); + break; + + case DPKVT_UI2: + pvarDst->VT.uiVal = varSrc.VT.uiVal; + break; + + case DPKVT_UI4: + pvarDst->VT.ulVal = varSrc.VT.ulVal; + break; + + default: + assert(FALSE); // This case is not handled + FailIf(TRUE, WMP_errNotYetImplemented); + + // *** FALL THROUGH *** + + case DPKVT_EMPTY: + memset(pvarDst, 0, sizeof(*pvarDst)); + assert(DPKVT_EMPTY == pvarDst->vt); + break; + } + +Cleanup: + return err; +} + + +void FreeDescMetadata(DPKPROPVARIANT *pvar) +{ + switch (pvar->vt) + { + case DPKVT_LPSTR: + PKFree((void **) &pvar->VT.pszVal); + break; + + case DPKVT_LPWSTR: + PKFree((void **) &pvar->VT.pwszVal); + break; + + default: + assert(FALSE); // This case is not handled + break; + + case DPKVT_EMPTY: + case DPKVT_UI2: + case DPKVT_UI4: + break; + } +} + + +ERR WriteDescMetadata(PKImageEncode *pIE, + const DPKPROPVARIANT var, + WmpDE *pwmpDE, + U32 *puiCurrDescMetadataOffset, + size_t *poffPos) +{ + ERR err = WMP_errSuccess; + WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc; + struct WMPStream* pWS = pIE->pStream; + U32 uiMetadataOffsetSize = 0; + U32 uiCount = 0; + U32 uiDataWrittenToOffset = 0; + U16 uiTemp = 0; + + if (0 == pDEMisc->uDescMetadataOffset || 0 == pDEMisc->uDescMetadataByteCount) + goto Cleanup; // Nothing to do here + + // Sanity check before - can be equal due to remaining metadata being DPKVT_EMPTY + assert(*puiCurrDescMetadataOffset <= pDEMisc->uDescMetadataByteCount); + + switch (var.vt) + { + case DPKVT_EMPTY: + break; + + case DPKVT_LPSTR: + CalcMetadataSizeLPSTR(var, &uiTemp, &uiMetadataOffsetSize, &uiCount); + pwmpDE->uCount = uiCount; + pwmpDE->uValueOrOffset = pDEMisc->uDescMetadataOffset + *puiCurrDescMetadataOffset; + Call(WriteWmpDE(pWS, poffPos, pwmpDE, (U8*)var.VT.pszVal, &uiDataWrittenToOffset)); + break; + + case DPKVT_LPWSTR: + CalcMetadataSizeLPWSTR(var, &uiTemp, &uiMetadataOffsetSize, &uiCount); + pwmpDE->uCount = uiCount; + pwmpDE->uValueOrOffset = pDEMisc->uDescMetadataOffset + *puiCurrDescMetadataOffset; + Call(WriteWmpDE(pWS, poffPos, pwmpDE, (U8*)var.VT.pwszVal, &uiDataWrittenToOffset)); + break; + + case DPKVT_UI2: + CalcMetadataSizeUI2(var, &uiTemp, &uiMetadataOffsetSize); + pwmpDE->uCount = 1; + pwmpDE->uValueOrOffset = var.VT.uiVal; + Call(WriteWmpDE(pWS, poffPos, pwmpDE, NULL, NULL)); + break; + + case DPKVT_UI4: + CalcMetadataSizeUI4(var, &uiTemp, &uiMetadataOffsetSize); + pwmpDE->uCount = 1; + pwmpDE->uValueOrOffset = var.VT.ulVal; + Call(WriteWmpDE(pWS, poffPos, pwmpDE, NULL, NULL)); + break; + + default: + assert(FALSE); // This case is not handled + FailIf(TRUE, WMP_errNotYetImplemented); + break; + } + + *puiCurrDescMetadataOffset += uiDataWrittenToOffset; + + // Sanity check after + assert(*puiCurrDescMetadataOffset <= pDEMisc->uDescMetadataByteCount); // Can be equal + +Cleanup: + return err; +} + + + +//================================================================ +// PKImageEncode_WMP +//================================================================ +ERR WriteContainerPre( + PKImageEncode* pIE) +{ + ERR err = WMP_errSuccess; + const U32 OFFSET_OF_PFD = 0x20; + struct WMPStream* pWS = pIE->pStream; + WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc; + PKPixelInfo PI; + size_t offPos = 0; + + U8 IIMM[2] = {'\x49', '\x49'}; + // const U32 cbWmpDEMisc = OFFSET_OF_PFD; + U32 cbMetadataOffsetSize = 0; + U16 cInactiveMetadata = 0; + U32 uiCurrDescMetadataOffset = 0; + + static WmpDE wmpDEs[] = + { + {WMP_tagDocumentName, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagImageDescription, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagCameraMake, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagCameraModel, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagPageName, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagPageNumber, WMP_typSHORT, 2, (U32) -1}, // Descriptive metadata + {WMP_tagSoftware, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagDateTime, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagArtist, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagHostComputer, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagRatingStars, WMP_typSHORT, 1, (U32) -1}, // Descriptive metadata + {WMP_tagRatingValue, WMP_typSHORT, 1, (U32) -1}, // Descriptive metadata + {WMP_tagCopyright, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata + {WMP_tagCaption, WMP_typBYTE, 1, (U32) -1}, // Descriptive metadata + + {WMP_tagXMPMetadata, WMP_typBYTE, 1, (U32) -1}, + {WMP_tagIPTCNAAMetadata, WMP_typBYTE, 1, (U32) -1}, + {WMP_tagPhotoshopMetadata, WMP_typBYTE, 1, (U32) -1}, + {WMP_tagEXIFMetadata, WMP_typLONG, 1, (U32) -1}, + {WMP_tagIccProfile, WMP_typUNDEFINED, 1, (U32) -1}, + {WMP_tagGPSInfoMetadata, WMP_typLONG, 1, (U32) -1}, + + {WMP_tagPixelFormat, WMP_typBYTE, 16, (U32) -1}, + {WMP_tagTransformation, WMP_typLONG, 1, (U32) -1}, + {WMP_tagImageWidth, WMP_typLONG, 1, (U32) -1}, + {WMP_tagImageHeight, WMP_typLONG, 1, (U32) -1}, + {WMP_tagWidthResolution, WMP_typFLOAT, 1, (U32) -1}, + {WMP_tagHeightResolution, WMP_typFLOAT, 1, (U32) -1}, + {WMP_tagImageOffset, WMP_typLONG, 1, (U32) -1}, + {WMP_tagImageByteCount, WMP_typLONG, 1, (U32) -1}, + {WMP_tagAlphaOffset, WMP_typLONG, 1, (U32) -1}, + {WMP_tagAlphaByteCount, WMP_typLONG, 1, (U32) -1}, + }; + U16 cWmpDEs = sizeof(wmpDEs) / sizeof(wmpDEs[0]); + WmpDE wmpDE = {0}; + size_t i = 0; + + U8* pbEXIFMetadata = NULL; + U8* pbGPSInfoMetadata = NULL; + + // const unsigned char Zero[0x20] = { 0 }; + const unsigned char Zero[sizeof(struct IFDEntry) * sizeof(wmpDEs) / sizeof(wmpDEs[0]) + sizeof(U32)] = { 0 }; + assert(SizeofIFDEntry * sizeof(wmpDEs) / sizeof(wmpDEs[0]) + sizeof(U32) > 0x20); + + //================ + Call(pWS->GetPos(pWS, &offPos)); + FailIf(0 != offPos, WMP_errUnsupportedFormat); + + //================ + // Header (8 bytes) + Call(pWS->Write(pWS, IIMM, sizeof(IIMM))); offPos += 2; + Call(PutUShort(pWS, offPos, 0x01bc)); offPos += 2; + Call(PutULong(pWS, offPos, (U32)OFFSET_OF_PFD)); offPos += 4; + + //================ + // Write overflow area + pDEMisc->uOffPixelFormat = (U32)offPos; + PI.pGUIDPixFmt = &pIE->guidPixFormat; + PixelFormatLookup(&PI, LOOKUP_FORWARD); + + //Call(pWS->Write(pWS, PI.pGUIDPixFmt, sizeof(*PI.pGUIDPixFmt))); offPos += 16; + /** following code is endian-agnostic **/ + { + unsigned char *pGuid = (unsigned char *) &pIE->guidPixFormat; + Call(PutULong(pWS, offPos, ((U32 *)pGuid)[0])); + Call(PutUShort(pWS, offPos + 4, ((U16 *)(pGuid + 4))[0])); + Call(PutUShort(pWS, offPos + 6, ((U16 *)(pGuid + 6))[0])); + Call(pWS->Write(pWS, pGuid + 8, 8)); + offPos += 16; + } + + //================ + // Tally up space required for descriptive metadata + Call(CalcMetadataOffsetSize(pIE, &cInactiveMetadata, &cbMetadataOffsetSize)); + cWmpDEs -= cInactiveMetadata; + + //================ + // PFD + assert (offPos <= OFFSET_OF_PFD); // otherwise stuff is overwritten + if (offPos < OFFSET_OF_PFD) + Call(pWS->Write(pWS, Zero, OFFSET_OF_PFD - offPos)); + offPos = (size_t)OFFSET_OF_PFD; + + if (!pIE->WMP.bHasAlpha || pIE->WMP.wmiSCP.uAlphaMode != 2) //no planar alpha + cWmpDEs -= 2; + + if (0 == pIE->cbXMPMetadataByteCount) + cWmpDEs -= 1; // No XMP metadata + + if (0 == pIE->cbIPTCNAAMetadataByteCount) + cWmpDEs -= 1; // No IPTCNAA metadata + + if (0 == pIE->cbPhotoshopMetadataByteCount) + cWmpDEs -= 1; // No Photoshop metadata + + if (0 == pIE->cbEXIFMetadataByteCount) + cWmpDEs -= 1; // No EXIF metadata + + if (0 == pIE->cbColorContext) + cWmpDEs -= 1; // No color context + + if (0 == pIE->cbGPSInfoMetadataByteCount) + cWmpDEs -= 1; // No GPSInfo metadata + + pDEMisc->uImageOffset = (U32)(offPos + sizeof(U16) + SizeofIFDEntry * cWmpDEs + sizeof(U32)); + + if (cbMetadataOffsetSize > 0) + { + pDEMisc->uDescMetadataByteCount = cbMetadataOffsetSize; + pDEMisc->uDescMetadataOffset = pDEMisc->uImageOffset; + pDEMisc->uImageOffset += cbMetadataOffsetSize; + } + + if (pIE->cbXMPMetadataByteCount > 0) + { + pDEMisc->uXMPMetadataOffset = pDEMisc->uImageOffset; + pDEMisc->uImageOffset += pIE->cbXMPMetadataByteCount; + } + + if (pIE->cbIPTCNAAMetadataByteCount > 0) + { + pDEMisc->uIPTCNAAMetadataOffset = pDEMisc->uImageOffset; + pDEMisc->uImageOffset += pIE->cbIPTCNAAMetadataByteCount; + } + + if (pIE->cbPhotoshopMetadataByteCount > 0) + { + pDEMisc->uPhotoshopMetadataOffset = pDEMisc->uImageOffset; + pDEMisc->uImageOffset += pIE->cbPhotoshopMetadataByteCount; + } + + if (pIE->cbEXIFMetadataByteCount > 0) + { + pDEMisc->uEXIFMetadataOffset = pDEMisc->uImageOffset; + pDEMisc->uImageOffset += (pDEMisc->uImageOffset & 1); + pDEMisc->uImageOffset += pIE->cbEXIFMetadataByteCount; + } + + if (pIE->cbColorContext > 0) + { + pDEMisc->uColorProfileOffset = pDEMisc->uImageOffset; + pDEMisc->uImageOffset += pIE->cbColorContext; + } + + if (pIE->cbGPSInfoMetadataByteCount > 0) + { + pDEMisc->uGPSInfoMetadataOffset = pDEMisc->uImageOffset; + pDEMisc->uImageOffset += (pDEMisc->uImageOffset & 1); + pDEMisc->uImageOffset += pIE->cbGPSInfoMetadataByteCount; + } + + Call(PutUShort(pWS, offPos, cWmpDEs)); offPos += 2; + Call(pWS->Write(pWS, Zero, SizeofIFDEntry * cWmpDEs + sizeof(U32))); + + //================ + wmpDE = wmpDEs[i++]; + assert(WMP_tagDocumentName == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarDocumentName, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagImageDescription == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarImageDescription, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagCameraMake == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCameraMake, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagCameraModel == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCameraModel, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagPageName == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarPageName, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagPageNumber == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarPageNumber, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagSoftware == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarSoftware, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagDateTime == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarDateTime, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagArtist == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarArtist, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagHostComputer == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarHostComputer, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagRatingStars == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarRatingStars, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagRatingValue == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarRatingValue, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagCopyright == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCopyright, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagCaption == wmpDE.uTag); + Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCaption, &wmpDE, + &uiCurrDescMetadataOffset, &offPos)); + + // XMP Metadata + wmpDE = wmpDEs[i++]; + assert(WMP_tagXMPMetadata == wmpDE.uTag); + if (pIE->cbXMPMetadataByteCount > 0) + { + U32 uiTemp; + wmpDE.uCount = pIE->cbXMPMetadataByteCount; + wmpDE.uValueOrOffset = pDEMisc->uXMPMetadataOffset; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbXMPMetadata, &uiTemp)); + } + + // IPTCNAA Metadata + wmpDE = wmpDEs[i++]; + assert(WMP_tagIPTCNAAMetadata == wmpDE.uTag); + if (pIE->cbIPTCNAAMetadataByteCount > 0) + { + U32 uiTemp; + wmpDE.uCount = pIE->cbIPTCNAAMetadataByteCount; + wmpDE.uValueOrOffset = pDEMisc->uIPTCNAAMetadataOffset; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbIPTCNAAMetadata, &uiTemp)); + } + + // Photoshop Metadata + wmpDE = wmpDEs[i++]; + assert(WMP_tagPhotoshopMetadata == wmpDE.uTag); + if (pIE->cbPhotoshopMetadataByteCount > 0) + { + U32 uiTemp; + wmpDE.uCount = pIE->cbPhotoshopMetadataByteCount; + wmpDE.uValueOrOffset = pDEMisc->uPhotoshopMetadataOffset; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbPhotoshopMetadata, &uiTemp)); + } + + // EXIF Metadata + wmpDE = wmpDEs[i++]; + assert(WMP_tagEXIFMetadata == wmpDE.uTag); + if (pIE->cbEXIFMetadataByteCount > 0) + { + U32 uiTemp; + if ((pDEMisc->uEXIFMetadataOffset & 1) != 0) + { + Call(pWS->SetPos(pWS, pDEMisc->uEXIFMetadataOffset)); + Call(pWS->Write(pWS, Zero, 1)); + } + pDEMisc->uEXIFMetadataOffset += (pDEMisc->uEXIFMetadataOffset & 1); + wmpDE.uValueOrOffset = pDEMisc->uEXIFMetadataOffset; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + Call(PKAlloc((void **) &pbEXIFMetadata, pIE->cbEXIFMetadataByteCount)); + uiTemp = pDEMisc->uEXIFMetadataOffset; + Call(BufferCopyIFD(pIE->pbEXIFMetadata, pIE->cbEXIFMetadataByteCount, 0, WMP_INTEL_ENDIAN, + pbEXIFMetadata - uiTemp, uiTemp + pIE->cbEXIFMetadataByteCount, &uiTemp)); + Call(pWS->SetPos(pWS, pDEMisc->uEXIFMetadataOffset)); + Call(pWS->Write(pWS, pbEXIFMetadata, pIE->cbEXIFMetadataByteCount)); + } + + // ICC Profile + wmpDE = wmpDEs[i++]; + assert(WMP_tagIccProfile == wmpDE.uTag); + if (pIE->cbColorContext > 0) + { + U32 uiTemp; + wmpDE.uCount = pIE->cbColorContext; + wmpDE.uValueOrOffset = pDEMisc->uColorProfileOffset; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbColorContext, &uiTemp)); + } + + // GPSInfo Metadata + wmpDE = wmpDEs[i++]; + assert(WMP_tagGPSInfoMetadata == wmpDE.uTag); + if (pIE->cbGPSInfoMetadataByteCount > 0) + { + U32 uiTemp; + if ((pDEMisc->uGPSInfoMetadataOffset & 1) != 0) + { + Call(pWS->SetPos(pWS, pDEMisc->uGPSInfoMetadataOffset)); + Call(pWS->Write(pWS, Zero, 1)); + } + pDEMisc->uGPSInfoMetadataOffset += (pDEMisc->uGPSInfoMetadataOffset & 1); + wmpDE.uValueOrOffset = pDEMisc->uGPSInfoMetadataOffset; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + Call(PKAlloc((void **) &pbGPSInfoMetadata, pIE->cbGPSInfoMetadataByteCount)); + uiTemp = pDEMisc->uGPSInfoMetadataOffset; + Call(BufferCopyIFD(pIE->pbGPSInfoMetadata, pIE->cbGPSInfoMetadataByteCount, 0, WMP_INTEL_ENDIAN, + pbGPSInfoMetadata - uiTemp, uiTemp + pIE->cbGPSInfoMetadataByteCount, &uiTemp)); + Call(pWS->SetPos(pWS, pDEMisc->uGPSInfoMetadataOffset)); + Call(pWS->Write(pWS, pbGPSInfoMetadata, pIE->cbGPSInfoMetadataByteCount)); + } + + wmpDE = wmpDEs[i++]; + assert(WMP_tagPixelFormat == wmpDE.uTag); + wmpDE.uValueOrOffset = pDEMisc->uOffPixelFormat; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagTransformation == wmpDE.uTag); + wmpDE.uValueOrOffset = pIE->WMP.oOrientation; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagImageWidth == wmpDE.uTag); + wmpDE.uValueOrOffset = pIE->uWidth; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagImageHeight == wmpDE.uTag); + wmpDE.uValueOrOffset = pIE->uHeight; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagWidthResolution == wmpDE.uTag); + *((float *) &wmpDE.uValueOrOffset) = pIE->fResX; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagHeightResolution == wmpDE.uTag); + *((float *) &wmpDE.uValueOrOffset) = pIE->fResY; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + wmpDE = wmpDEs[i++]; + assert(WMP_tagImageOffset == wmpDE.uTag); + wmpDE.uValueOrOffset = pDEMisc->uImageOffset; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + // fix up in WriteContainerPost() + wmpDE = wmpDEs[i++]; + assert(WMP_tagImageByteCount == wmpDE.uTag); + pDEMisc->uOffImageByteCount = (U32)offPos; + wmpDE.uValueOrOffset = 0; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) + { + // fix up in WriteContainerPost() + wmpDE = wmpDEs[i++]; + assert(WMP_tagAlphaOffset == wmpDE.uTag); + pDEMisc->uOffAlphaOffset = (U32)offPos; + wmpDE.uValueOrOffset = 0; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + + // fix up in WriteContainerPost() + wmpDE = wmpDEs[i++]; + assert(WMP_tagAlphaByteCount == wmpDE.uTag); + pDEMisc->uOffAlphaByteCount = (U32)offPos; + wmpDE.uValueOrOffset = 0; + Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); + } + + //================ + Call(PutULong(pWS, offPos, 0)); offPos += 4; + + assert(0 == (offPos & 1)); + if (pDEMisc->uColorProfileOffset > 0 || pDEMisc->uDescMetadataOffset > 0 || + pDEMisc->uXMPMetadataOffset > 0 || pDEMisc->uIPTCNAAMetadataOffset > 0 || + pDEMisc->uPhotoshopMetadataOffset > 0 || pDEMisc->uEXIFMetadataOffset > 0 || + pDEMisc->uGPSInfoMetadataOffset > 0) + { + assert(pDEMisc->uColorProfileOffset == offPos || + pDEMisc->uDescMetadataOffset == offPos || + pDEMisc->uXMPMetadataOffset == offPos || + pDEMisc->uIPTCNAAMetadataOffset == offPos || + pDEMisc->uPhotoshopMetadataOffset == offPos || + pDEMisc->uEXIFMetadataOffset == offPos || + pDEMisc->uGPSInfoMetadataOffset == offPos); + + // OK, now skip to image offset + Call(pWS->SetPos(pWS, pDEMisc->uImageOffset)); + offPos = pDEMisc->uImageOffset; + } + assert(pDEMisc->uImageOffset == offPos); + +Cleanup: + if (pbEXIFMetadata != NULL) + PKFree((void **) &pbEXIFMetadata); + if (pbGPSInfoMetadata != NULL) + PKFree((void **) &pbGPSInfoMetadata); + return err; +} + + + +ERR WriteContainerPost( + PKImageEncode* pIE) +{ + ERR err = WMP_errSuccess; + + struct WMPStream* pWS = pIE->pStream; + WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc; + size_t offPos; + + WmpDE deImageByteCount = {WMP_tagImageByteCount, WMP_typLONG, 1, 0}; + WmpDE deAlphaOffset = {WMP_tagAlphaOffset, WMP_typLONG, 1, 0}; + WmpDE deAlphaByteCount = {WMP_tagAlphaByteCount, WMP_typLONG, 1, 0}; + + deImageByteCount.uValueOrOffset = pIE->WMP.nCbImage; + offPos = pDEMisc->uOffImageByteCount; + Call(WriteWmpDE(pWS, &offPos, &deImageByteCount, NULL, NULL)); + + //Alpha + if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) + { + deAlphaOffset.uValueOrOffset = pIE->WMP.nOffAlpha; + offPos = pDEMisc->uOffAlphaOffset; + Call(WriteWmpDE(pWS, &offPos, &deAlphaOffset, NULL, NULL)); + + deAlphaByteCount.uValueOrOffset = pIE->WMP.nCbAlpha + pIE->WMP.nOffAlpha; + offPos = pDEMisc->uOffAlphaByteCount; + Call(WriteWmpDE(pWS, &offPos, &deAlphaByteCount, NULL, NULL)); + } + +Cleanup: + return err; +} + + +//================================================ +ERR PKImageEncode_Initialize_WMP( + PKImageEncode* pIE, + struct WMPStream* pStream, + void* pvParam, + size_t cbParam) +{ + ERR err = WMP_errSuccess; + + FailIf(sizeof(pIE->WMP.wmiSCP) != cbParam, WMP_errInvalidArgument); + + pIE->WMP.wmiSCP = *(CWMIStrCodecParam*)pvParam; + pIE->WMP.wmiSCP_Alpha = *(CWMIStrCodecParam*)pvParam; + pIE->pStream = pStream; + + pIE->WMP.wmiSCP.pWStream = pIE->pStream; + pIE->WMP.wmiSCP_Alpha.pWStream = pIE->pStream; + +Cleanup: + return err; +} + +ERR PKImageEncode_Terminate_WMP( + PKImageEncode* pIE) +{ + ERR err = WMP_errSuccess; + UNREFERENCED_PARAMETER( pIE ); + return err; +} + + +ERR PKImageEncode_EncodeContent_Init( + PKImageEncode* pIE, + PKPixelInfo PI, + U32 cLine, + U8* pbPixels, + U32 cbStride) +{ + ERR err = WMP_errSuccess; + + // init codec + pIE->WMP.wmiI.cWidth = pIE->uWidth; + pIE->WMP.wmiI.cHeight = pIE->uHeight; + pIE->WMP.wmiI.bdBitDepth = PI.bdBitDepth; + pIE->WMP.wmiI.cBitsPerUnit = PI.cbitUnit; + pIE->WMP.wmiI.bRGB = !(PI.grBit & PK_pixfmtBGR); + pIE->WMP.wmiI.cfColorFormat = PI.cfColorFormat; + pIE->WMP.wmiI.oOrientation = pIE->WMP.oOrientation; + + // Set the fPaddedUserBuffer if the following conditions are met + if (0 == ((size_t)pbPixels % 128) && // Frame buffer is aligned to 128-byte boundary + 0 == (pIE->uWidth % 16) && // Horizontal resolution is multiple of 16 + 0 == (cLine % 16) && // Vertical resolution is multiple of 16 + 0 == (cbStride % 128)) // Stride is a multiple of 128 bytes + { + pIE->WMP.wmiI.fPaddedUserBuffer = TRUE; + // Note that there are additional conditions in strenc_x86.c's strEncOpt + // which could prevent optimization from being engaged + } + + //if (pIE->WMP.bHasAlpha) + //{ + // pIE->WMP.wmiSCP.cChannel = PI.cChannel - 1; + // pIE->WMP.wmiI.cfColorFormat = PI.cfStripAlpha; + //} + //else + + if(PI.cfColorFormat == NCOMPONENT && (!(PI.grBit & PK_pixfmtHasAlpha)))//N-channel without Alpha + pIE->WMP.wmiSCP.cChannel = PI.cChannel; + else + pIE->WMP.wmiSCP.cChannel = PI.cChannel - 1;//other formats and (N-channel + Alpha) + + pIE->idxCurrentLine = 0; + + pIE->WMP.wmiSCP.fMeasurePerf = TRUE; + FailIf(ICERR_OK != ImageStrEncInit(&pIE->WMP.wmiI, &pIE->WMP.wmiSCP, &pIE->WMP.ctxSC), WMP_errFail); + +Cleanup: + return err; +} + +ERR PKImageEncode_EncodeContent_Encode( + PKImageEncode* pIE, + U32 cLine, + U8* pbPixels, + U32 cbStride) +{ + ERR err = WMP_errSuccess; + U32 i = 0; + + //================================ + for (i = 0; i < cLine; i += 16) + { + Bool f420 = ( pIE->WMP.wmiI.cfColorFormat == YUV_420 || + (pIE->WMP.wmiSCP.bYUVData && pIE->WMP.wmiSCP.cfColorFormat==YUV_420) ); + CWMImageBufferInfo wmiBI = { 0 }; + wmiBI.pv = pbPixels + cbStride * i / (f420 ? 2 : 1); + wmiBI.cLine = min(16, cLine - i); + wmiBI.cbStride = cbStride; + FailIf(ICERR_OK != ImageStrEncEncode(pIE->WMP.ctxSC, &wmiBI), WMP_errFail); + } + pIE->idxCurrentLine += cLine; + +Cleanup: + return err; +} + +ERR PKImageEncode_EncodeContent_Term(PKImageEncode* pIE) +{ + ERR err = WMP_errSuccess; + + FailIf(ICERR_OK != ImageStrEncTerm(pIE->WMP.ctxSC), WMP_errFail); + +Cleanup: + return err; +} + +ERR PKImageEncode_EncodeContent( + PKImageEncode* pIE, + PKPixelInfo PI, + U32 cLine, + U8* pbPixels, + U32 cbStride) +{ + ERR err = WMP_errSuccess; + size_t offPos = 0; + + Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); + pIE->WMP.nOffImage = (Long)offPos; + + Call(PKImageEncode_EncodeContent_Init(pIE, PI, cLine, pbPixels, cbStride)); + Call(PKImageEncode_EncodeContent_Encode(pIE, cLine, pbPixels, cbStride)); + Call(PKImageEncode_EncodeContent_Term(pIE)); + + Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); + pIE->WMP.nCbImage = (Long)offPos - pIE->WMP.nOffImage; + +Cleanup: + return err; +} + + +ERR PKImageEncode_EncodeAlpha_Init( + PKImageEncode* pIE, + PKPixelInfo PI, + U32 cLine, + U8* pbPixels, + U32 cbStride) +{ + ERR err = WMP_errSuccess; + + UNREFERENCED_PARAMETER( cLine ); + UNREFERENCED_PARAMETER( pbPixels ); + UNREFERENCED_PARAMETER( cbStride ); + + pIE->WMP.wmiI_Alpha = pIE->WMP.wmiI; + + pIE->WMP.wmiI_Alpha.cWidth = pIE->uWidth; + pIE->WMP.wmiI_Alpha.cHeight = pIE->uHeight; + pIE->WMP.wmiI_Alpha.bdBitDepth = PI.bdBitDepth; + pIE->WMP.wmiI_Alpha.cBitsPerUnit = PI.cbitUnit; + pIE->WMP.wmiI_Alpha.bRGB = !(PI.grBit & PK_pixfmtBGR); + pIE->WMP.wmiI.oOrientation = pIE->WMP.oOrientation; +// pIE->WMP.wmiI_Alpha.cLeadingPadding += pIE->WMP.wmiSCP.cChannel; +// pIE->WMP.wmiI_Alpha.cLeadingPadding += PI.cChannel - 1; + + switch (pIE->WMP.wmiI.bdBitDepth) + { + case BD_8: + pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) - 1; + break; + + case BD_16: + case BD_16S: + case BD_16F: + pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(U16) - 1; + break; + + case BD_32: + case BD_32S: + case BD_32F: + pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(float) - 1; + break; + + case BD_5: + case BD_10: + case BD_565: + default: + break; + } + +// pIE->WMP.wmiSCP_Alpha.uAlphaMode = 1; + + + //assert(pIE->WMP.wmiI_Alpha.cfColorFormat == CF_RGB); // only RGBA is supported for now! + pIE->WMP.wmiI_Alpha.cfColorFormat = Y_ONLY; + + pIE->WMP.wmiSCP_Alpha.cfColorFormat = Y_ONLY; + + pIE->idxCurrentLine = 0; + pIE->WMP.wmiSCP_Alpha.fMeasurePerf = TRUE; + FailIf(ICERR_OK != ImageStrEncInit(&pIE->WMP.wmiI_Alpha, &pIE->WMP.wmiSCP_Alpha, &pIE->WMP.ctxSC_Alpha), WMP_errFail); + +Cleanup: + return err; +} + +ERR PKImageEncode_EncodeAlpha_Encode( + PKImageEncode* pIE, + U32 cLine, + U8* pbPixels, + U32 cbStride) +{ + ERR err = WMP_errSuccess; + U32 i = 0; + + //================================ + for (i = 0; i < cLine; i += 16) + { + CWMImageBufferInfo wmiBI = { 0 }; + wmiBI.pv = pbPixels + cbStride * i; + wmiBI.cLine = min(16, cLine - i); + wmiBI.cbStride = cbStride; + FailIf(ICERR_OK != ImageStrEncEncode(pIE->WMP.ctxSC_Alpha, &wmiBI), WMP_errFail); + } + pIE->idxCurrentLine += cLine; + +Cleanup: + return err; +} + +ERR PKImageEncode_EncodeAlpha_Term(PKImageEncode* pIE) +{ + ERR err = WMP_errSuccess; + + FailIf(ICERR_OK != ImageStrEncTerm(pIE->WMP.ctxSC_Alpha), WMP_errFail); + +Cleanup: + return err; +} + +ERR PKImageEncode_EncodeAlpha( + PKImageEncode* pIE, + PKPixelInfo PI, + U32 cLine, + U8* pbPixels, + U32 cbStride) +{ + ERR err = WMP_errSuccess; + size_t offPos = 0; + + Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); + if ((offPos & 1) != 0) + { + // Make the mark even if it is odd by inserting a pad byte + char zero = 0; + Call(pIE->pStream->Write(pIE->pStream, &zero, 1)); + offPos++; + } + pIE->WMP.nOffAlpha = (Long)offPos; + + Call(PKImageEncode_EncodeAlpha_Init(pIE, PI, cLine, pbPixels, cbStride)); + Call(PKImageEncode_EncodeAlpha_Encode(pIE, cLine, pbPixels, cbStride)); + Call(PKImageEncode_EncodeAlpha_Term(pIE)); + + Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); + pIE->WMP.nCbAlpha = (Long)offPos - pIE->WMP.nOffAlpha; + +Cleanup: + return err; +} + + + +static ERR SetMetadata(PKImageEncode *pIE, const U8 *pbMetadata, U32 cbMetadata, U8** pbSet, U32* pcbSet) +{ + ERR err = WMP_errSuccess; + + // Fail if the caller called us after we've already written the header out + if (pIE->fHeaderDone) + { + assert(FALSE); // Message to programmer + err = WMP_errOutOfSequence; + goto Cleanup; + } + + // Make a copy of the metadata + PKFree((void **) pbSet); + *pcbSet = 0; + + Call(PKAlloc((void **) pbSet, cbMetadata)); + memcpy(*pbSet, pbMetadata, cbMetadata); + *pcbSet = cbMetadata; + +Cleanup: + return err; +} + + + +ERR PKImageEncode_SetColorContext_WMP(PKImageEncode *pIE, + const U8 *pbColorContext, + U32 cbColorContext) +{ + return SetMetadata(pIE, pbColorContext, cbColorContext, &pIE->pbColorContext, &pIE->cbColorContext); +} + + + +ERR PKImageEncode_SetXMPMetadata_WMP(PKImageEncode *pIE, const U8 *pbXMPMetadata, U32 cbXMPMetadata) +{ // same as the other Set's, but make sure dc:format is image/vnd.ms-photo + ERR err = WMP_errSuccess; + char* pbTemp = 0; + U32 cbTemp; + char* pszFormatBegin; + // const char* pszXMPMetadata = (const char*)pbXMPMetadata; + size_t cbBuffer; + + // Fail if the caller called us after we've already written the header out + FailIf(pIE->fHeaderDone, WMP_errOutOfSequence); + + // Free any previously set XMP metadata + PKFree((void **) &pIE->pbXMPMetadata); + pIE->cbXMPMetadataByteCount = 0; + + // allocate a block big enough for data passed in plus added trailing null plus added HD Photo dc:format + // there may already be a trailing null (but ps doesn't seem to) + // there may already be a dc:format we will replace with HD Photo's + // but anyway this block will be large enough guaranteed + cbBuffer = cbXMPMetadata + 1 + sizeof("") - 1 + sizeof("") - 1 + sizeof(szHDPhotoFormat) - 1; + Call(PKAlloc((void **) &pbTemp, cbBuffer)); + memcpy(pbTemp, pbXMPMetadata, cbXMPMetadata); // Make a copy of the metadata + pbTemp[cbXMPMetadata] = '\0'; + cbXMPMetadata = (U32)strlen(pbTemp); + pszFormatBegin = strstr(pbTemp, ""); + if ( pszFormatBegin != 0 ) + { + char* pszFormatEnd; + const char* pszLessThan; + + pszFormatEnd = strstr(pszFormatBegin, ""); + FailIf(pszFormatEnd == 0, WMP_errFail); + pszLessThan = strchr(pszFormatBegin + sizeof("") - 1, '<'); + FailIf(pszLessThan != pszFormatEnd, WMP_errFail); + pszFormatEnd += sizeof("") - 1; + + // photoshop doesn't put a trailing null, so we don't either + // hd and tiff don't put a trailing null, so we don't either + cbTemp = cbXMPMetadata - (U32) ( pszFormatEnd - pszFormatBegin ) + sizeof(szHDPhotoFormat) - 1; + assert(cbTemp <= cbBuffer); + FailIf(0 != STRCPY_SAFE(pszFormatBegin, + cbBuffer - (pszFormatBegin - pbTemp), + szHDPhotoFormat), + WMP_errBufferOverflow); + memcpy(pszFormatBegin + sizeof(szHDPhotoFormat) - 1, pbXMPMetadata + ( pszFormatEnd - pbTemp ), + cbXMPMetadata - ( pszFormatEnd - pbTemp )); + } + else + { + cbTemp = cbXMPMetadata; + } + + pIE->pbXMPMetadata = (U8 *) pbTemp; + pIE->cbXMPMetadataByteCount = cbTemp; + return ( err ); + +Cleanup: + PKFree((void **) &pbTemp); + pIE->cbXMPMetadataByteCount = 0; + return err; +} + + + +ERR PKImageEncode_SetEXIFMetadata_WMP(PKImageEncode *pIE, const U8 *pbEXIFMetadata, U32 cbEXIFMetadata) +{ + return SetMetadata(pIE, pbEXIFMetadata, cbEXIFMetadata, + &pIE->pbEXIFMetadata, &pIE->cbEXIFMetadataByteCount); +} + + + +ERR PKImageEncode_SetGPSInfoMetadata_WMP(PKImageEncode *pIE, const U8 *pbGPSInfoMetadata, U32 cbGPSInfoMetadata) +{ + return SetMetadata(pIE, pbGPSInfoMetadata, cbGPSInfoMetadata, + &pIE->pbGPSInfoMetadata, &pIE->cbGPSInfoMetadataByteCount); +} + + + +ERR PKImageEncode_SetIPTCNAAMetadata_WMP(PKImageEncode *pIE, const U8 *pbIPTCNAAMetadata, U32 cbIPTCNAAMetadata) +{ + return SetMetadata(pIE, pbIPTCNAAMetadata, cbIPTCNAAMetadata, + &pIE->pbIPTCNAAMetadata, &pIE->cbIPTCNAAMetadataByteCount); +} + + + +ERR PKImageEncode_SetPhotoshopMetadata_WMP(PKImageEncode *pIE, const U8 *pbPhotoshopMetadata, U32 cbPhotoshopMetadata) +{ + return SetMetadata(pIE, pbPhotoshopMetadata, cbPhotoshopMetadata, + &pIE->pbPhotoshopMetadata, &pIE->cbPhotoshopMetadataByteCount); +} + + + +ERR PKImageEncode_SetDescriptiveMetadata_WMP(PKImageEncode *pIE, const DESCRIPTIVEMETADATA *pSrcMeta) +{ + ERR err = WMP_errSuccess; + DESCRIPTIVEMETADATA *pDstMeta = &pIE->sDescMetadata; + + // Fail if the caller called us after we've already written the header out + if (pIE->fHeaderDone) + { + assert(FALSE); // Message to programmer + FailIf(TRUE, WMP_errOutOfSequence); + } + + // Make a copy of the descriptive metadata + Call(CopyDescMetadata(&pDstMeta->pvarImageDescription, pSrcMeta->pvarImageDescription)); + Call(CopyDescMetadata(&pDstMeta->pvarCameraMake, pSrcMeta->pvarCameraMake)); + Call(CopyDescMetadata(&pDstMeta->pvarCameraModel, pSrcMeta->pvarCameraModel)); + Call(CopyDescMetadata(&pDstMeta->pvarSoftware, pSrcMeta->pvarSoftware)); + Call(CopyDescMetadata(&pDstMeta->pvarDateTime, pSrcMeta->pvarDateTime)); + Call(CopyDescMetadata(&pDstMeta->pvarArtist, pSrcMeta->pvarArtist)); + Call(CopyDescMetadata(&pDstMeta->pvarCopyright, pSrcMeta->pvarCopyright)); + Call(CopyDescMetadata(&pDstMeta->pvarRatingStars, pSrcMeta->pvarRatingStars)); + Call(CopyDescMetadata(&pDstMeta->pvarRatingValue, pSrcMeta->pvarRatingValue)); + Call(CopyDescMetadata(&pDstMeta->pvarCaption, pSrcMeta->pvarCaption)); + Call(CopyDescMetadata(&pDstMeta->pvarDocumentName, pSrcMeta->pvarDocumentName)); + Call(CopyDescMetadata(&pDstMeta->pvarPageName, pSrcMeta->pvarPageName)); + Call(CopyDescMetadata(&pDstMeta->pvarPageNumber, pSrcMeta->pvarPageNumber)); + Call(CopyDescMetadata(&pDstMeta->pvarHostComputer, pSrcMeta->pvarHostComputer)); + +Cleanup: + return err; +} + + + +ERR PKImageEncode_WritePixels_WMP( + PKImageEncode* pIE, + U32 cLine, + U8* pbPixels, + U32 cbStride) +{ + ERR err = WMP_errSuccess; + // U32 i = 0; + PKPixelInfo PI; + + // Performing non-banded encode + assert(BANDEDENCSTATE_UNINITIALIZED == pIE->WMP.eBandedEncState); + pIE->WMP.eBandedEncState = BANDEDENCSTATE_NONBANDEDENCODE; + + PI.pGUIDPixFmt = &pIE->guidPixFormat; + PixelFormatLookup(&PI, LOOKUP_FORWARD); + pIE->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha); + + if (!pIE->fHeaderDone) + { + // write metadata + Call(WriteContainerPre(pIE)); + + pIE->fHeaderDone = !FALSE; + } + +/* if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2){ + pIE->WMP.wmiSCP_Alpha = pIE->WMP.wmiSCP; + } +*/ + Call(PKImageEncode_EncodeContent(pIE, PI, cLine, pbPixels, cbStride)); + if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2){//planar alpha + Call(PKImageEncode_EncodeAlpha(pIE, PI, cLine, pbPixels, cbStride)); + } + + Call(WriteContainerPost(pIE)); + +Cleanup: + return err; +} + + +ERR PKImageEncode_WritePixelsBandedBegin_WMP(PKImageEncode* pIE, struct WMPStream *pPATempFile) +{ + ERR err = WMP_errSuccess; + + // Just make sure that we are in the correct state to begin a banded decode + assert(BANDEDENCSTATE_UNINITIALIZED == pIE->WMP.eBandedEncState); + pIE->WMP.eBandedEncState = BANDEDENCSTATE_INIT; + + // Save the planar alpha tempfile for future use + pIE->WMP.pPATempFile = pPATempFile; + +//Cleanup: + return err; +} + +ERR PKImageEncode_WritePixelsBanded_WMP(PKImageEncode* pIE, U32 cLine, U8* pbPixels, U32 cbStride, Bool fLastCall) +{ + ERR err = WMP_errSuccess; + PKPixelInfo PI = {0}; + Bool fPI = FALSE; + BANDEDENCSTATE eEncStateOrig = pIE->WMP.eBandedEncState; + struct WMPStream *pPATempFile = pIE->WMP.pPATempFile; + + // Unless this is the last call, reject inputs which are not multiples of 16 + FailIf(!fLastCall && 0 != cLine % 16, WMP_errMustBeMultipleOf16LinesUntilLastCall); + + if (!pIE->fHeaderDone || BANDEDENCSTATE_INIT == pIE->WMP.eBandedEncState) + { + PI.pGUIDPixFmt = &pIE->guidPixFormat; + PixelFormatLookup(&PI, LOOKUP_FORWARD); + pIE->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha); + fPI = TRUE; + + // Check if this is planar alpha: banded encode requires temp file + if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) + { + FailIf(NULL == pPATempFile, WMP_errPlanarAlphaBandedEncRequiresTempFile); + } + } + + if (!pIE->fHeaderDone) + { + // write metadata + assert(fPI); + Call(WriteContainerPre(pIE)); + pIE->fHeaderDone = !FALSE; + } + + if (BANDEDENCSTATE_INIT == pIE->WMP.eBandedEncState) + { + // Record start of main content for future call to WriteContainerPost + size_t offPos; + Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); + pIE->WMP.nOffImage = (Long)offPos; + + assert(fPI); + Call(PKImageEncode_EncodeContent_Init(pIE, PI, cLine, pbPixels, cbStride)); + pIE->WMP.eBandedEncState = BANDEDENCSTATE_ENCODING; + } + + Call(PKImageEncode_EncodeContent_Encode(pIE, cLine, pbPixels, cbStride)); + if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) + { + //planar alpha + if (BANDEDENCSTATE_INIT == eEncStateOrig) + { + size_t offStart; + + // We assume the following which allows us to avoid saving state + Call(pPATempFile->GetPos(pPATempFile, &offStart)); + assert(0 == offStart); + assert(pIE->WMP.wmiSCP_Alpha.pWStream == pIE->WMP.wmiSCP.pWStream); + + // For planar alpha, we write the file to a temp file + pIE->WMP.wmiSCP_Alpha.pWStream = pPATempFile; + Call(PKImageEncode_EncodeAlpha_Init(pIE, PI, cLine, pbPixels, cbStride)); + } + + Call(PKImageEncode_EncodeAlpha_Encode(pIE, cLine, pbPixels, cbStride)); + } + +Cleanup: + return err; +} + +ERR PKImageEncode_WritePixelsBandedEnd_WMP(PKImageEncode* pIE) +{ + ERR err = WMP_errSuccess; + struct WMPStream *pMainStream = pIE->WMP.wmiSCP.pWStream; + size_t offAlpha; + + assert(BANDEDENCSTATE_ENCODING == pIE->WMP.eBandedEncState); + + // Finish off main content, update its length ptr for WriteContainerPost + Call(PKImageEncode_EncodeContent_Term(pIE)); + Call(pMainStream->GetPos(pIE->pStream, &offAlpha)); + pIE->WMP.nCbImage = (Long)offAlpha - pIE->WMP.nOffImage; + + if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) + { + size_t cbAlpha; + size_t cbBytesCopied; + struct WMPStream *pAlphaStream = pIE->WMP.wmiSCP_Alpha.pWStream; + + assert(pAlphaStream != pMainStream); // Otherwise we didn't use a temp file + + // Close it up - this causes write to temp file + Call(PKImageEncode_EncodeAlpha_Term(pIE)); + + // Calculate size of alpha bitstream and its new offset + Call(pAlphaStream->GetPos(pAlphaStream, &cbAlpha)); + + // Copy alpha bitstream to end of main stream + cbBytesCopied = 0; + Call(pAlphaStream->SetPos(pAlphaStream, 0)); + while (cbBytesCopied < cbAlpha) + { + char rgbBuf[TEMPFILE_COPYBUF_SIZE]; + size_t cbCopy; + + cbCopy = min(sizeof(rgbBuf), cbAlpha - cbBytesCopied); + Call(pAlphaStream->Read(pAlphaStream, rgbBuf, cbCopy)); + Call(pMainStream->Write(pMainStream, rgbBuf, cbCopy)); + + cbBytesCopied += cbCopy; + } + assert(cbBytesCopied == cbAlpha); + + // Update alpha offset/length for WriteContainerPost + pIE->WMP.nOffAlpha = (Long)offAlpha; + pIE->WMP.nCbAlpha = (Long)cbAlpha; + } + + Call(WriteContainerPost(pIE)); + +Cleanup: + return err; +} + + +ERR PKImageEncode_Transcode_WMP( + PKImageEncode* pIE, + PKImageDecode* pID, + CWMTranscodingParam* pParam) +{ + ERR err = WMP_errSuccess; + Float fResX = 0, fResY = 0; + PKPixelFormatGUID pixGUID = {0}; + CWMTranscodingParam tcParamAlpha; + size_t offPos = 0; + Bool fPlanarAlpha; + PKPixelInfo PI; + + struct WMPStream* pWSDec = NULL; + struct WMPStream* pWSEnc= pIE->pStream; + + // pass through metadata + Call(pID->GetPixelFormat(pID, &pixGUID)); + Call(pIE->SetPixelFormat(pIE, pixGUID)); + + Call(pIE->SetSize(pIE, (I32)pParam->cWidth, (I32)pParam->cHeight)); + + Call(pID->GetResolution(pID, &fResX, &fResY)); + Call(pIE->SetResolution(pIE, fResX, fResY)); + + PI.pGUIDPixFmt = &pIE->guidPixFormat; + PixelFormatLookup(&PI, LOOKUP_FORWARD); + pIE->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha) && (2 == pParam->uAlphaMode); + assert(0 == pIE->WMP.bHasAlpha || (pParam->uAlphaMode == 2)); // Decode alpha mode does not match encode alpha mode! + + // Check for any situations where transcoder is being asked to convert alpha - we can't do this + // NOTE: Decoder's bHasAlpha parameter really means, "has PLANAR alpha" + PI.pGUIDPixFmt = &pixGUID; + PixelFormatLookup(&PI, LOOKUP_FORWARD); + FailIf(0 == (PI.grBit & PK_pixfmtHasAlpha) && pParam->uAlphaMode != 0, + WMP_errAlphaModeCannotBeTranscoded); // Destination is planar/interleaved, src has no alpha + FailIf(!!(PI.grBit & PK_pixfmtHasAlpha) && 2 == pParam->uAlphaMode && + FALSE == pID->WMP.bHasAlpha, WMP_errAlphaModeCannotBeTranscoded); // Destination is planar, src is interleaved + FailIf(!!(PI.grBit & PK_pixfmtHasAlpha) && 3 == pParam->uAlphaMode && + pID->WMP.bHasAlpha, WMP_errAlphaModeCannotBeTranscoded); // Destination is interleaved, src is planar + assert(/*pParam->uAlphaMode >= 0 &&*/ pParam->uAlphaMode <= 3); // All the above statements make this assumption + + fPlanarAlpha = pIE->WMP.bHasAlpha && (2 == pParam->uAlphaMode); + + // write matadata + Call(WriteContainerPre(pIE)); + + // Copy transcoding params for alpha (codec changes the struct) + if (fPlanarAlpha) + tcParamAlpha = *pParam; + + // write compressed bitstream + Call(pID->GetRawStream(pID, &pWSDec)); + + FailIf(ICERR_OK != WMPhotoTranscode(pWSDec, pWSEnc, pParam), WMP_errFail); + Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); + pIE->WMP.nCbImage = (Long)offPos - pIE->WMP.nOffImage; + + if (fPlanarAlpha) + { + pIE->WMP.nOffAlpha = (Long)offPos; + + // Cue the stream to alpha block + assert(pID->WMP.wmiDEMisc.uAlphaOffset > 0); + Call(pWSDec->SetPos(pWSDec, pID->WMP.wmiDEMisc.uAlphaOffset)); + + FailIf(ICERR_OK != WMPhotoTranscode(pWSDec, pWSEnc, &tcParamAlpha), WMP_errFail); + Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); + pIE->WMP.nCbAlpha = (Long)offPos - pIE->WMP.nOffAlpha; + } + + // fixup matadata + Call(WriteContainerPost(pIE)); + +Cleanup: + return err; +} + +ERR PKImageEncode_CreateNewFrame_WMP( + PKImageEncode* pIE, + void* pvParam, + size_t cbParam) +{ + ERR err = WMP_errSuccess; + + UNREFERENCED_PARAMETER( pIE ); + UNREFERENCED_PARAMETER( pvParam ); + UNREFERENCED_PARAMETER( cbParam ); + + Call(WMP_errNotYetImplemented); + +Cleanup: + return err; +} + +ERR PKImageEncode_Release_WMP( + PKImageEncode** ppIE) +{ + ERR err = WMP_errSuccess; + + PKImageEncode *pIE = *ppIE; + pIE->pStream->Close(&pIE->pStream); + + PKFree((void **) &pIE->pbColorContext); + pIE->cbColorContext = 0; + PKFree((void **) &pIE->pbXMPMetadata); + pIE->cbXMPMetadataByteCount = 0; + PKFree((void **) &pIE->pbEXIFMetadata); + pIE->cbEXIFMetadataByteCount = 0; + PKFree((void **) &pIE->pbGPSInfoMetadata); + pIE->cbGPSInfoMetadataByteCount = 0; + PKFree((void **) &pIE->pbIPTCNAAMetadata); + pIE->cbIPTCNAAMetadataByteCount = 0; + PKFree((void **) &pIE->pbPhotoshopMetadata); + pIE->cbPhotoshopMetadataByteCount = 0; + + // Free descriptive metadata + FreeDescMetadata(&pIE->sDescMetadata.pvarImageDescription); + FreeDescMetadata(&pIE->sDescMetadata.pvarCameraMake); + FreeDescMetadata(&pIE->sDescMetadata.pvarCameraModel); + FreeDescMetadata(&pIE->sDescMetadata.pvarSoftware); + FreeDescMetadata(&pIE->sDescMetadata.pvarDateTime); + FreeDescMetadata(&pIE->sDescMetadata.pvarArtist); + FreeDescMetadata(&pIE->sDescMetadata.pvarCopyright); + FreeDescMetadata(&pIE->sDescMetadata.pvarRatingStars); + FreeDescMetadata(&pIE->sDescMetadata.pvarRatingValue); + FreeDescMetadata(&pIE->sDescMetadata.pvarCaption); + FreeDescMetadata(&pIE->sDescMetadata.pvarDocumentName); + FreeDescMetadata(&pIE->sDescMetadata.pvarPageName); + FreeDescMetadata(&pIE->sDescMetadata.pvarPageNumber); + FreeDescMetadata(&pIE->sDescMetadata.pvarHostComputer); + + Call(PKFree((void **) ppIE)); + +Cleanup: + return err; +} + +//---------------------------------------------------------------- +ERR PKImageEncode_Create_WMP(PKImageEncode** ppIE) +{ + ERR err = WMP_errSuccess; + + PKImageEncode* pIE = NULL; + + Call(PKImageEncode_Create(ppIE)); + + pIE = *ppIE; + pIE->Initialize = PKImageEncode_Initialize_WMP; + pIE->Terminate = PKImageEncode_Terminate_WMP; + pIE->SetColorContext = PKImageEncode_SetColorContext_WMP; + pIE->SetDescriptiveMetadata = PKImageEncode_SetDescriptiveMetadata_WMP; + pIE->WritePixels = PKImageEncode_WritePixels_WMP; + + pIE->WritePixelsBandedBegin = PKImageEncode_WritePixelsBandedBegin_WMP; + pIE->WritePixelsBanded = PKImageEncode_WritePixelsBanded_WMP; + pIE->WritePixelsBandedEnd = PKImageEncode_WritePixelsBandedEnd_WMP; + + pIE->Transcode = PKImageEncode_Transcode_WMP; + pIE->CreateNewFrame = PKImageEncode_CreateNewFrame_WMP; + pIE->Release = PKImageEncode_Release_WMP; + pIE->bWMP = TRUE; + +Cleanup: + return err; +} + + +//================================================================ +// PKImageDecode_WMP +//================================================================ +ERR ParsePFDEntry( + PKImageDecode* pID, + U16 uTag, + U16 uType, + U32 uCount, + U32 uValue) +{ + ERR err = WMP_errSuccess; + ERR errTmp = WMP_errSuccess; + PKPixelInfo PI; + struct WMPStream* pWS = pID->pStream; + // size_t offPos = 0; + + union uf{ + U32 uVal; + Float fVal; + }ufValue = {0}; + + //================================ + switch (uTag) + { + case WMP_tagPixelFormat: + { + unsigned char *pGuid = (unsigned char *) &pID->guidPixFormat; + /** following code is endian-agnostic **/ + Call(GetULong(pWS, uValue, (U32 *)pGuid)); + Call(GetUShort(pWS, uValue + 4, (unsigned short *)(pGuid + 4))); + Call(GetUShort(pWS, uValue + 6, (unsigned short *)(pGuid + 6))); + Call(pWS->Read(pWS, pGuid + 8, 8)); + + PI.pGUIDPixFmt = &pID->guidPixFormat; + PixelFormatLookup(&PI, LOOKUP_FORWARD); + + pID->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha); + pID->WMP.wmiI.cBitsPerUnit = PI.cbitUnit; + pID->WMP.wmiI.bRGB = !(PI.grBit & PK_pixfmtBGR); + + break; + } + + case WMP_tagTransformation: + FailIf(1 != uCount, WMP_errUnsupportedFormat); + assert(uValue < O_MAX); + pID->WMP.fOrientationFromContainer = TRUE; + pID->WMP.oOrientationFromContainer = uValue; + break; + + case WMP_tagImageWidth: + FailIf(0 == uValue, WMP_errUnsupportedFormat); + break; + + case WMP_tagImageHeight: + FailIf(0 == uValue, WMP_errUnsupportedFormat); + break; + + case WMP_tagImageOffset: + FailIf(1 != uCount, WMP_errUnsupportedFormat); + pID->WMP.wmiDEMisc.uImageOffset = uValue; + break; + + case WMP_tagImageByteCount: + FailIf(1 != uCount, WMP_errUnsupportedFormat); + pID->WMP.wmiDEMisc.uImageByteCount = uValue; + break; + + case WMP_tagAlphaOffset: + FailIf(1 != uCount, WMP_errUnsupportedFormat); + pID->WMP.wmiDEMisc.uAlphaOffset = uValue; + break; + + case WMP_tagAlphaByteCount: + FailIf(1 != uCount, WMP_errUnsupportedFormat); + pID->WMP.wmiDEMisc.uAlphaByteCount = uValue; + break; + + case WMP_tagWidthResolution: + FailIf(1 != uCount, WMP_errUnsupportedFormat); + ufValue.uVal = uValue; + pID->fResX = ufValue.fVal; + break; + + case WMP_tagHeightResolution: + FailIf(1 != uCount, WMP_errUnsupportedFormat); + ufValue.uVal = uValue; + pID->fResY = ufValue.fVal; + break; + + case WMP_tagIccProfile: + pID->WMP.wmiDEMisc.uColorProfileByteCount = uCount; + pID->WMP.wmiDEMisc.uColorProfileOffset = uValue; + break; + + case WMP_tagXMPMetadata: + pID->WMP.wmiDEMisc.uXMPMetadataByteCount = uCount; + pID->WMP.wmiDEMisc.uXMPMetadataOffset = uValue; + break; + + case WMP_tagEXIFMetadata: + pID->WMP.wmiDEMisc.uEXIFMetadataOffset = uValue; + CallIgnoreError(errTmp, StreamCalcIFDSize(pWS, uValue, &pID->WMP.wmiDEMisc.uEXIFMetadataByteCount)); + break; + + case WMP_tagGPSInfoMetadata: + pID->WMP.wmiDEMisc.uGPSInfoMetadataOffset = uValue; + CallIgnoreError(errTmp, StreamCalcIFDSize(pWS, uValue, &pID->WMP.wmiDEMisc.uGPSInfoMetadataByteCount)); + break; + + case WMP_tagIPTCNAAMetadata: + pID->WMP.wmiDEMisc.uIPTCNAAMetadataByteCount = uCount; + pID->WMP.wmiDEMisc.uIPTCNAAMetadataOffset = uValue; + break; + + case WMP_tagPhotoshopMetadata: + pID->WMP.wmiDEMisc.uPhotoshopMetadataByteCount = uCount; + pID->WMP.wmiDEMisc.uPhotoshopMetadataOffset = uValue; + break; + + case WMP_tagCompression: + case WMP_tagImageType: + case WMP_tagImageDataDiscard: + case WMP_tagAlphaDataDiscard: + break; + + // Descriptive Metadata + case WMP_tagImageDescription: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarImageDescription)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarImageDescription.vt); + break; + + case WMP_tagCameraMake: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarCameraMake)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarCameraMake.vt); + break; + + case WMP_tagCameraModel: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarCameraModel)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarCameraModel.vt); + break; + + case WMP_tagSoftware: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarSoftware)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarSoftware.vt); + break; + + case WMP_tagDateTime: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarDateTime)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarDateTime.vt); + break; + + case WMP_tagArtist: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarArtist)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarArtist.vt); + break; + + case WMP_tagCopyright: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarCopyright)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarCopyright.vt); + break; + + case WMP_tagRatingStars: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarRatingStars)); + assert(DPKVT_UI2 == pID->WMP.sDescMetadata.pvarRatingStars.vt); + break; + + case WMP_tagRatingValue: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarRatingValue)); + assert(DPKVT_UI2 == pID->WMP.sDescMetadata.pvarRatingValue.vt); + break; + + case WMP_tagCaption: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarCaption)); + assert((DPKVT_BYREF | DPKVT_UI1) == pID->WMP.sDescMetadata.pvarCaption.vt); + + // Change type from C-style byte array to LPWSTR + assert((U8*)pID->WMP.sDescMetadata.pvarCaption.VT.pwszVal == + pID->WMP.sDescMetadata.pvarCaption.VT.pbVal); + assert(0 == pID->WMP.sDescMetadata.pvarCaption.VT.pwszVal[uCount/sizeof(U16) - 1]); // Confirm null-term + // make sure null term (ReadPropvar allocated enough space for this) + pID->WMP.sDescMetadata.pvarCaption.VT.pwszVal[uCount/sizeof(U16)] = 0; + pID->WMP.sDescMetadata.pvarCaption.vt = DPKVT_LPWSTR; + break; + + case WMP_tagDocumentName: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarDocumentName)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarDocumentName.vt); + break; + + case WMP_tagPageName: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarPageName)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarPageName.vt); + break; + + case WMP_tagPageNumber: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarPageNumber)); + assert(DPKVT_UI4 == pID->WMP.sDescMetadata.pvarPageNumber.vt); + break; + + case WMP_tagHostComputer: + CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, + &pID->WMP.sDescMetadata.pvarHostComputer)); + assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarHostComputer.vt); + break; + + default: +#if defined(_DEBUG) || defined(DBG) + // This was originally unconditional, spamming stderr on every file open. + fprintf(stderr, "Unrecognized WMPTag: %d(%#x), %d, %d, %#x" CRLF, + (int)uTag, (int)uTag, (int)uType, (int)uCount, (int)uValue); +#endif + break; + } + +Cleanup: + return err; +} + +ERR ParsePFD( + PKImageDecode* pID, + size_t offPos, + U16 cEntry) +{ + ERR err = WMP_errSuccess; + struct WMPStream* pWS = pID->pStream; + U16 i = 0; + + for (i = 0; i < cEntry; ++i) + { + U16 uTag = 0; + U16 uType = 0; + U32 uCount = 0; + U32 uValue = 0; + + Call(GetUShort(pWS, offPos, &uTag)); offPos += 2; + Call(GetUShort(pWS, offPos, &uType)); offPos += 2; + Call(GetULong(pWS, offPos, &uCount)); offPos += 4; + Call(GetULong(pWS, offPos, &uValue)); offPos += 4; + + Call(ParsePFDEntry(pID, uTag, uType, uCount, uValue)); + } + + pID->WMP.bHasAlpha = ((pID->WMP.bHasAlpha) && (pID->WMP.wmiDEMisc.uAlphaOffset != 0) && (pID->WMP.wmiDEMisc.uAlphaByteCount != 0));//has planar alpha + +Cleanup: + return err; +} + +ERR ReadContainer( + PKImageDecode* pID) +{ + ERR err = WMP_errSuccess; + + struct WMPStream* pWS = pID->pStream; + size_t offPos = 0; + + char szSig[2] = {0}; + U16 uWmpID = 0; + U32 offPFD = 0; + U16 cPFDEntry = 0; + U8 bVersion; + + //================================ + Call(pWS->GetPos(pWS, &offPos)); + FailIf(0 != offPos, WMP_errUnsupportedFormat); + + //================================ + // Header + Call(pWS->Read(pWS, szSig, sizeof(szSig))); offPos += 2; + FailIf(szSig != strstr(szSig, "II"), WMP_errUnsupportedFormat); + + Call(GetUShort(pWS, offPos, &uWmpID)); offPos += 2; + FailIf(WMP_valWMPhotoID != (0x00FF & uWmpID), WMP_errUnsupportedFormat); + + // We accept version 00 and version 01 bitstreams - all others rejected + bVersion = (0xFF00 & uWmpID) >> 8; + FailIf(bVersion != 0 && bVersion != 1, WMP_errUnsupportedFormat); + + Call(GetULong(pWS, offPos, &offPFD)); offPos += 4; + + //================================ + // PFD + offPos = (size_t)offPFD; + Call(GetUShort(pWS, offPos, &cPFDEntry)); offPos += 2; + FailIf(0 == cPFDEntry || USHRT_MAX == cPFDEntry, WMP_errUnsupportedFormat); + Call(ParsePFD(pID, offPos, cPFDEntry)); + + //================================ + Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uImageOffset)); + +Cleanup: + return err; +} + + +//================================================ +ERR PKImageDecode_Initialize_WMP( + PKImageDecode* pID, + struct WMPStream* pWS) +{ + ERR err = WMP_errSuccess; + + CWMImageInfo* pII = NULL; + + //================================ + Call(PKImageDecode_Initialize(pID, pWS)); + + //================================ + Call(ReadContainer(pID)); + + //================================ + pID->WMP.wmiSCP.pWStream = pWS; + pID->WMP.DecoderCurrMBRow = 0; + pID->WMP.cLinesDecoded = 0; + pID->WMP.cLinesCropped = 0; + pID->WMP.fFirstNonZeroDecode = FALSE; + + FailIf(ICERR_OK != ImageStrDecGetInfo(&pID->WMP.wmiI, &pID->WMP.wmiSCP), WMP_errFail); + assert(Y_ONLY <= pID->WMP.wmiSCP.cfColorFormat && pID->WMP.wmiSCP.cfColorFormat < CFT_MAX); + assert(BD_SHORT == pID->WMP.wmiSCP.bdBitDepth || BD_LONG == pID->WMP.wmiSCP.bdBitDepth); + + // If HD Photo container provided an orientation, this should override bitstream orientation + // If container did NOT provide an orientation, force O_NONE. This is to be consistent with + // Vista behaviour, which is to ignore bitstream orientation (only looks at container). + if (pID->WMP.fOrientationFromContainer) + { + pID->WMP.wmiI.oOrientation = pID->WMP.oOrientationFromContainer; + } + else + { + // Force to O_NONE to match Vista decode behaviour + pID->WMP.wmiI.oOrientation = O_NONE; + } + + pII = &pID->WMP.wmiI; + pID->uWidth = (U32)pII->cWidth; + pID->uHeight = (U32)pII->cHeight; + +Cleanup: + return err; +} + + +ERR PKImageDecode_GetSize_WMP( + PKImageDecode* pID, + I32* piWidth, + I32* piHeight) +{ + if (pID->WMP.wmiI.oOrientation >= O_RCW) + { + *piWidth = (I32)pID->uHeight; + *piHeight = (I32)pID->uWidth; + } + else + { + *piWidth = (I32)pID->uWidth; + *piHeight = (I32)pID->uHeight; + } + return WMP_errSuccess; +} + + +ERR PKImageDecode_GetRawStream_WMP( + PKImageDecode* pID, + struct WMPStream** ppWS) +{ + ERR err = WMP_errSuccess; + struct WMPStream* pWS = pID->pStream; + + *ppWS = NULL; + Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uImageOffset)); + *ppWS = pWS; + +Cleanup: + return err; +} + +ERR PKImageDecode_Copy_WMP( + PKImageDecode* pID, + const PKRect* pRect, + U8* pb, + U32 cbStride) +{ + ERR err = WMP_errSuccess; + U32 cThumbnailScale; + U32 linesperMBRow; + CWMImageBufferInfo wmiBI = { 0 }; +#ifdef REENTRANT_MODE + U8 *pbLowMemAdj = NULL; + U32 i, cMBRow; + U32 cMBRowStart; +#endif // REENTRANT_MODE + struct WMPStream* pWS = pID->pStream; + U8 tempAlphaMode = 0; + wmiBI.pv = pb; + wmiBI.cLine = pRect->Height; + wmiBI.cbStride = cbStride; +#ifdef REENTRANT_MODE + // In REENTRANT_MODE, we allow rectangles with any top left corner (not just (0,0)) +#else + FailIf(0 != pRect->X, WMP_errInvalidParameter); + FailIf(0 != pRect->Y, WMP_errInvalidParameter); +#endif // REENTRANT_MODE + + cThumbnailScale = 1; + if (pID->WMP.wmiI.cThumbnailWidth > 0) + { + while(cThumbnailScale * pID->WMP.wmiI.cThumbnailWidth < pID->uWidth) + cThumbnailScale <<= 1; + } + // note the following implementation can't handle fractional linesperMBRow limiting + // us to >= 1/256 thumbnail which is unfortunate, but all the PS plugin needs is 1/256 + // and I didn't care to get into floating point or a bunch of conditional tests or + // other rewrite for a case not needed nor tested by PS plugin. sorry. + linesperMBRow = 16 / cThumbnailScale; + +#ifdef REENTRANT_MODE + if (0 == pID->WMP.DecoderCurrMBRow) + { +#endif // REENTRANT_MODE + // Set the fPaddedUserBuffer if the following conditions are met + if (0 == ((size_t)pb % 128) && // Frame buffer is aligned to 128-byte boundary + 0 == (pRect->Height % 16) && // Horizontal resolution is multiple of 16 + 0 == (pRect->Width % 16) && // Vertical resolution is multiple of 16 + 0 == (cbStride % 128)) // Stride is a multiple of 128 bytes + { + pID->WMP.wmiI.fPaddedUserBuffer = TRUE; + // Note that there are additional conditions in strdec_x86.c's strDecOpt + // which could prevent optimization from being engaged + } +#ifdef REENTRANT_MODE + } +#endif // REENTRANT_MODE + //if(pID->WMP.wmiSCP.uAlphaMode != 1) + if((!pID->WMP.bHasAlpha) || (pID->WMP.wmiSCP.uAlphaMode != 1)) + { + if(pID->WMP.bHasAlpha)//planar alpha + { + tempAlphaMode = pID->WMP.wmiSCP.uAlphaMode; + pID->WMP.wmiSCP.uAlphaMode = 0; + } + pID->WMP.wmiSCP.fMeasurePerf = TRUE; +#ifdef REENTRANT_MODE + if (0 == pID->WMP.DecoderCurrMBRow) + { + Call(pID->WMP.wmiSCP.pWStream->GetPos(pID->WMP.wmiSCP.pWStream, &(pID->WMP.cMarker))); + FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI, &pID->WMP.wmiSCP, &pID->WMP.ctxSC), WMP_errFail); + } + // Re-entrant mode incurs 1 MBR delay, so to get 0th MBR, we have to ask for 1st MBR + cMBRow = ((U32) pID->WMP.cLinesCropped + pRect->Y + pRect->Height + + (pRect->Y + pRect->Height >= (I32) pID->WMP.wmiI.cROIHeight ? linesperMBRow - 1 : 0)) / // round up if last MBR + linesperMBRow + 1; + cMBRowStart = ((U32) pID->WMP.cLinesCropped + pRect->Y) / linesperMBRow + 1; + // if current request starts before current state, then rewind. + if (cMBRowStart < pID->WMP.DecoderCurrMBRow) + { + pID->WMP.DecoderCurrMBRow = 0; + pID->WMP.cLinesDecoded = 0; + pID->WMP.cLinesCropped = 0; + pID->WMP.fFirstNonZeroDecode = FALSE; + FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail); + Call(pID->WMP.wmiSCP.pWStream->SetPos(pID->WMP.wmiSCP.pWStream, pID->WMP.cMarker)); + FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI, &pID->WMP.wmiSCP, &pID->WMP.ctxSC), WMP_errFail); + } + + // In "Low Memory mode", we don't have full frame buffer. We therefore cannot rotate the image. + // We can flip H, V and HV, but no rotations. + FailIf(pID->WMP.wmiI.oOrientation >= O_RCW, WMP_errFail); + + // In low-memory mode, the full frame buffer is unavailable. This doesn't seem to + // matter in O_NONE and O_FLIPH, but for O_FLIPV and O_FLIPVH, outputMBRow tries to write to + // the bottom of full-frame buffer. Adjust the buffer pointer to compensate. + if (O_FLIPV == pID->WMP.wmiI.oOrientation || O_FLIPVH == pID->WMP.wmiI.oOrientation) + { + I32 iActualY2 = pRect->Y + pRect->Height; + pbLowMemAdj = pb - (pID->WMP.wmiI.cROIHeight - (iActualY2 - pID->WMP.cLinesCropped)) * cbStride; + } + else + { + pbLowMemAdj = pb - pRect->Y * cbStride; + } + wmiBI.pv = pbLowMemAdj; + + for (i = (U32)pID->WMP.DecoderCurrMBRow; i < cMBRow; i++) + { + size_t cLinesDecoded; + wmiBI.uiFirstMBRow = i; + wmiBI.uiLastMBRow = i; + FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC, &wmiBI, &cLinesDecoded), WMP_errFail); + pID->WMP.cLinesDecoded = cLinesDecoded; + if (FALSE == pID->WMP.fFirstNonZeroDecode && cLinesDecoded > 0) + { + pID->WMP.cLinesCropped += (linesperMBRow - cLinesDecoded); + pID->WMP.fFirstNonZeroDecode = TRUE; + // update cMBRow if partial MB row cropped + cMBRow = ((U32) pID->WMP.cLinesCropped + pRect->Y + pRect->Height + + (pRect->Y + pRect->Height >= (I32) pID->WMP.wmiI.cROIHeight ? linesperMBRow - 1 : 0)) / // round up if last MBR + linesperMBRow + 1; + } + + if (0 == cLinesDecoded && i > 0) + { + pID->WMP.cLinesCropped += linesperMBRow; + // update cMBRow if whole MB row cropped + cMBRow++; + } + } + wmiBI.pv = pbLowMemAdj; + + // If we're past the top of the image, then we're done, so terminate. + if (linesperMBRow * (cMBRow - 1) >= (U32) pID->WMP.cLinesCropped + pID->WMP.wmiI.cROIHeight) { + FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail); + } + pID->WMP.DecoderCurrMBRow = cMBRow; // Set to next possible MBRow that is decodable + +#else + FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI, &pID->WMP.wmiSCP, &pID->WMP.ctxSC), WMP_errFail); + FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC, &wmiBI), WMP_errFail); + FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail); +#endif //REENTRANT_MODE + + if(pID->WMP.bHasAlpha)//planar alpha + { + pID->WMP.wmiSCP.uAlphaMode = tempAlphaMode; + } + } + +// if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode == 2) +// if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode != 1) + if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode != 0) + { + pID->WMP.wmiI_Alpha = pID->WMP.wmiI; + pID->WMP.wmiSCP_Alpha = pID->WMP.wmiSCP; + +// assert(pID->WMP.wmiI_Alpha.cfColorFormat == CF_RGB); // only RGBA is supported for now! + pID->WMP.wmiI_Alpha.cfColorFormat = Y_ONLY; + + switch (pID->WMP.wmiI.bdBitDepth) + { + case BD_8: + pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) - 1; + break; + + case BD_16: + case BD_16S: + case BD_16F: + pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(U16) - 1; + break; + + case BD_32: + case BD_32S: + case BD_32F: + pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(float) - 1; + break; + + case BD_5: + case BD_10: + case BD_565: + default: + break; + } + + pID->WMP.wmiSCP_Alpha.fMeasurePerf = TRUE; + Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uAlphaOffset)); +#ifdef REENTRANT_MODE + if (0 == pID->WMP.DecoderCurrAlphaMBRow) // add this to WMP struct! + { + FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail); + } + + // Re-entrant mode incurs 1 MBR delay, so to get 0th MBR, we have to ask for 1st MBR + cMBRow = ((U32) pID->WMP.cLinesCropped + pRect->Y + pRect->Height + + (pRect->Y + pRect->Height >= (I32) pID->WMP.wmiI.cROIHeight ? linesperMBRow - 1 : 0)) / // round up if last MBR + linesperMBRow + 1; + cMBRowStart = ((U32) pID->WMP.cLinesCropped + pRect->Y) / linesperMBRow + 1; + // if current request starts before current state, then rewind. + if (cMBRowStart < pID->WMP.DecoderCurrAlphaMBRow) + { + pID->WMP.DecoderCurrAlphaMBRow = 0; + FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail); + FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail); + } + + for (i = (U32)pID->WMP.DecoderCurrAlphaMBRow; i < cMBRow; i++) + { + size_t cLinesDecoded; + wmiBI.uiFirstMBRow = i; + wmiBI.uiLastMBRow = i; + FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC_Alpha, &wmiBI, &cLinesDecoded), WMP_errFail); + } + + // If we're past the top of the image, then we're done, so terminate + if (linesperMBRow * (cMBRow - 1) >= (U32) pID->WMP.cLinesCropped + pID->WMP.wmiI.cROIHeight) { + FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail); + } + pID->WMP.DecoderCurrAlphaMBRow = cMBRow; // Set to next possible MBRow that is decodable + wmiBI.pv = pb; +#else + FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail); + FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC_Alpha, &wmiBI), WMP_errFail); + FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail); +#endif //REENTRANT_MODE + } + + pID->idxCurrentLine += pRect->Height; + +Cleanup: + return err; +} + + +ERR PKImageDecode_GetMetadata_WMP(PKImageDecode *pID, U32 uOffset, U32 uByteCount, U8 *pbGot, U32 *pcbGot) +{ + ERR err = WMP_errSuccess; + + if (pbGot && uOffset) + { + struct WMPStream* pWS = pID->pStream; + size_t iCurrPos; + + FailIf(*pcbGot < uByteCount, WMP_errBufferOverflow); + Call(pWS->GetPos(pWS, &iCurrPos)); + Call(pWS->SetPos(pWS, uOffset)); + Call(pWS->Read(pWS, pbGot, uByteCount)); + Call(pWS->SetPos(pWS, iCurrPos)); + } + +Cleanup: + if (Failed(err)) + *pcbGot = 0; + else + *pcbGot = uByteCount; + + return err; +} + + + +ERR PKImageDecode_GetColorContext_WMP(PKImageDecode *pID, U8 *pbColorContext, U32 *pcbColorContext) +{ + return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uColorProfileOffset, + pID->WMP.wmiDEMisc.uColorProfileByteCount, pbColorContext, pcbColorContext); +} + + +ERR PKImageDecode_GetXMPMetadata_WMP(PKImageDecode *pID, U8 *pbXMPMetadata, U32 *pcbXMPMetadata) +{ + return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uXMPMetadataOffset, + pID->WMP.wmiDEMisc.uXMPMetadataByteCount, pbXMPMetadata, pcbXMPMetadata); +} + + +ERR PKImageDecode_GetEXIFMetadata_WMP(PKImageDecode *pID, U8 *pbEXIFMetadata, U32 *pcbEXIFMetadata) +{ + return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uEXIFMetadataOffset, + pID->WMP.wmiDEMisc.uEXIFMetadataByteCount, pbEXIFMetadata, pcbEXIFMetadata); +} + + +ERR PKImageDecode_GetGPSInfoMetadata_WMP(PKImageDecode *pID, U8 *pbGPSInfoMetadata, U32 *pcbGPSInfoMetadata) +{ + return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uGPSInfoMetadataOffset, + pID->WMP.wmiDEMisc.uGPSInfoMetadataByteCount, pbGPSInfoMetadata, pcbGPSInfoMetadata); +} + + +ERR PKImageDecode_GetIPTCNAAMetadata_WMP(PKImageDecode *pID, U8 *pbIPTCNAAMetadata, U32 *pcbIPTCNAAMetadata) +{ + return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uIPTCNAAMetadataOffset, + pID->WMP.wmiDEMisc.uIPTCNAAMetadataByteCount, pbIPTCNAAMetadata, pcbIPTCNAAMetadata); +} + + +ERR PKImageDecode_GetPhotoshopMetadata_WMP(PKImageDecode *pID, U8 *pbPhotoshopMetadata, U32 *pcbPhotoshopMetadata) +{ + return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uPhotoshopMetadataOffset, + pID->WMP.wmiDEMisc.uPhotoshopMetadataByteCount, pbPhotoshopMetadata, pcbPhotoshopMetadata); +} + + +ERR PKImageDecode_GetDescriptiveMetadata_WMP(PKImageDecode *pID, DESCRIPTIVEMETADATA *pDescMetadata) +{ + ERR err = WMP_errSuccess; + *pDescMetadata = pID->WMP.sDescMetadata; + return err; +} + + +ERR PKImageDecode_Release_WMP(PKImageDecode** ppID) +{ + ERR err = WMP_errSuccess; + PKImageDecode *pID; + + if (NULL == ppID) + goto Cleanup; + + pID = *ppID; + + // Free descriptive metadata + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarImageDescription); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCameraMake); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCameraModel); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarSoftware); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarDateTime); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarArtist); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCopyright); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarRatingStars); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarRatingValue); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCaption); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarDocumentName); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarPageName); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarPageNumber); + FreeDescMetadata(&pID->WMP.sDescMetadata.pvarHostComputer); + + // Release base class + Call(PKImageDecode_Release(ppID)); + +Cleanup: + return err; +} + + + +ERR PKImageDecode_Create_WMP(PKImageDecode** ppID) +{ + ERR err = WMP_errSuccess; + PKImageDecode* pID = NULL; + + Call(PKImageDecode_Create(ppID)); + + pID = *ppID; + pID->Initialize = PKImageDecode_Initialize_WMP; + pID->GetSize = PKImageDecode_GetSize_WMP; + pID->GetRawStream = PKImageDecode_GetRawStream_WMP; + pID->Copy = PKImageDecode_Copy_WMP; + pID->GetColorContext = PKImageDecode_GetColorContext_WMP; + pID->GetDescriptiveMetadata = PKImageDecode_GetDescriptiveMetadata_WMP; + pID->Release = PKImageDecode_Release_WMP; + +Cleanup: + return err; +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlueJxr.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlueJxr.o new file mode 100644 index 0000000..95f1bd1 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGlueJxr.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGluePFC.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGluePFC.c new file mode 100644 index 0000000..e44b12c --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGluePFC.c @@ -0,0 +1,2338 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include + +#include +#include + +//================================================================ +// PKFormatConverter +//================================================================ +#define HLF_MIN 0.00006103515625f +#define HLF_MAX 65504.0f + +#define HLF_MIN_BITS 0x0400 +#define HLF_MAX_BITS 0x7bff + +#define HLF_MIN_BITS_NEG (HLF_MIN_BITS | 0x8000) +#define HLF_MAX_BITS_NEG (HLF_MAX_BITS | 0x8000) + +#define HLF_QNaN_BITZS 0x7fff + +// simple and slow implementation of half <-> float conversion +static U32 Convert_Half_To_Float(U16 u16) +{ + // 1s5e10m -> 1s8e23m + const U32 s = (u16 >> 15) & 0x0001; + const U32 e = (u16 >> 10) & 0x001f; + const U32 m = (u16 >> 0) & 0x03ff; + + if (0 == e) // 0, denorm + { + return s << 31; + } + else if (~(~0 << 5) == e) // inf, snan, qnan + { + return (s << 31) | ~(~0 << 8) << 23| (m << 13); + } + + return (s << 31) | ((e - 15 + 127) << 23) | (m << 13); // norm +} + + +static U16 Convert_Float_To_Half(float f) +{ + // 1s5e10m -> 1s8e23m + const U32 iFloat = *(U32*)&f; // Convert float to U32 + + if (f != f) + { + return (U16)(iFloat | HLF_QNaN_BITZS); // +QNaN, -QNaN + } + else if (f < -HLF_MAX) + { + return HLF_MAX_BITS_NEG; + } + else if (HLF_MAX < f) + { + return HLF_MAX_BITS; + } + else if (-HLF_MIN < f && f < HLF_MIN) + { + return (U16)((iFloat >> 16) & 0x8000); // +0, -0 + } + + // Cut-and-paste from C++, introduce scope so we can decl more vars + { + const U32 s = (iFloat >> 31) & 0x00000001; + const U32 e = (iFloat >> 23) & 0x000000ff; + const U32 m = (iFloat >> 0) & 0x007fffff; + + return (U16) ((s << 15) | ((e - 127 + 15) << 10) | (m >> 13)); + } +} + + +static U8 Convert_Float_To_U8(float f) +{ + // convert from linear scRGB to non-linear sRGB + if (f <= 0) + { + return 0; + } + else if (f <= 0.0031308f) + { + return (U8)((255.0f * f * 12.92f) + 0.5f); + } + else if (f < 1.0f) + { + return (U8)((255.0f * ((1.055f * (float)pow(f, 1.0 / 2.4)) - 0.055f)) + 0.5f); + } + else + { + return 255; + } +} + +static U8 Convert_AlphaFloat_To_U8(float f) +{ + // alpha is converted differently than RGB in scRGB + if (f <= 0) + { + return 0; + } + else if (f < 1.0f) + { + return (U8)((255.0f * f) + 0.5f); + } + else + { + return 255; + } +} + + +ERR RGB24_BGR24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + I32 i = 0, j = 0; + + UNREFERENCED_PARAMETER( pFC ); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = 0; j < pRect->Width * 3; j += 3) + { + // swap red with blue + U8 t = pb[j]; + pb[j] = pb[j + 2]; + pb[j + 2] = t; + } + + pb += cbStride; + } + + return WMP_errSuccess; +} + +ERR BGR24_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + return RGB24_BGR24(pFC, pRect, pb, cbStride); +} + +ERR RGB24_BGR32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + I32 i = 0, j = 0; + + UNREFERENCED_PARAMETER( pFC ); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = 0; j < pRect->Width; j++) + { + // swap red with blue + U8 t = pb[3*j]; + pb[4*j] = pb[3*j + 2]; + pb[4*j + 1] = pb[3*j + 1]; + pb[4*j + 2] = t; + } + + pb += cbStride; + } + + return WMP_errSuccess; +} + +ERR BGR32_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + I32 i = 0, j = 0; + + UNREFERENCED_PARAMETER( pFC ); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = 0; j < pRect->Width; j++) + { + // swap red with blue + U8 t = pb[4*j]; + pb[3*j] = pb[4*j + 2]; + pb[3*j + 1] = pb[4*j + 1]; + pb[3*j + 2] = t; + } + + pb += cbStride; + } + + return WMP_errSuccess; +} + +ERR RGB24_Gray8(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + I32 i = 0, j = 0, k = 0; + + UNREFERENCED_PARAMETER( pFC ); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = 0, k = 0; j < pRect->Width * 3; j += 3, ++k) + { + U8 r = pb[j]; + U8 g = pb[j + 1]; + U8 b = pb[j + 2]; + + pb[k] = r / 4 + g / 2 + b / 8 + 16; + } + + pb += cbStride; + } + + return WMP_errSuccess; +} + +ERR BGR24_Gray8(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + ERR err = WMP_errSuccess; + + Call(BGR24_RGB24(pFC, pRect, pb, cbStride)); + Call(RGB24_Gray8(pFC, pRect, pb, cbStride)); + +Cleanup: + return err; +} + +ERR Gray8_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + I32 i = 0, j = 0, k = 0; + + UNREFERENCED_PARAMETER( pFC ); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = pRect->Width - 1, k = 3 * j; 0 <= j; j--, k -= 3) + { + U8 v = pb[j]; + + pb[k] = v; + pb[k + 1] = v; + pb[k + 2] = v; + } + + pb += cbStride; + } + + return WMP_errSuccess; +} + +ERR Gray8_BGR24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + return Gray8_RGB24(pFC, pRect, pb, cbStride); +} + +#if 0 +ERR RGB48_BGR48(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + ERR err = WMP_errSuccess; + + I32 i = 0, j = 0; + + UNREFERENCED_PARAMETER( pFC ); + + Call(PKFormatConverter_Copy(pFC, pRect, pb, cbStride)); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = 0; j < pRect->Width; j += 3) + { + U16* ps = (U16*)pb; + + // swap red with blue + U16 t = ps[j]; + ps[j] = ps[j + 2]; + ps[j + 2] = t; + } + + pb += cbStride; + } + +Cleanup: + return err; +} + +ERR BGR48_RGB48(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + return RGB48_BGR48(pFC, pRect, pb, cbStride); +} + +ERR RGB48_Gray16(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + ERR err = WMP_errSuccess; + + I32 i = 0, j = 0, k = 0; + + UNREFERENCED_PARAMETER( pFC ); + + Call(PKFormatConverter_Copy(pFC, pRect, pb, cbStride)); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = 0, k = 0; j < pRect->Width; j += 3, ++k) + { + U16* ps = (U16*)pb; + + // Y = r / 4 + g / 2 + b / 8 + 16 + U16 r = ps[j]; + U16 g = ps[j + 1]; + U16 b = ps[j + 2]; + + ps[k] = r / 4 + g / 2 + b / 8 + 16; + } + + pb += cbStride; + } + +Cleanup: + return err; +} +#endif + +ERR RGBA128Fixed_RGBA128Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX4 = 4 * pRect->Width; // 4 == R, G, B, A + const float fltCvtFactor = 1.0F / (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const I32 *piSrcPixel = (I32*)pfltDstPixel; + + for (x = 0; x < iWidthX4; x++) + pfltDstPixel[x] = piSrcPixel[x] * fltCvtFactor; + } + + return WMP_errSuccess; +} + + +ERR RGBA128Float_RGBA128Fixed(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX4 = 4 * pRect->Width; // 4 == R, G, B, A + const float fltCvtFactor = (float)(1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + I32 *piDstPixel = (I32*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidthX4; x++) + piDstPixel[x] = (I32) (pfltSrcPixel[x] * fltCvtFactor + 0.5F); + } + + return WMP_errSuccess; +} + + + +ERR RGB96Fixed_RGB96Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX3 = 3 * pRect->Width; // 3 == R, G, B + const float fltCvtFactor = 1.0F / (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const I32 *piSrcPixel = (I32*)pfltDstPixel; + + for (x = 0; x < iWidthX3; x++) + pfltDstPixel[x] = piSrcPixel[x] * fltCvtFactor; + } + + return WMP_errSuccess; +} + + +ERR RGB128Fixed_RGB96Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const I32 *piSrcPixel = (I32*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + pfltDstPixel[3*x] = piSrcPixel[4*x] * fltCvtFactor; + pfltDstPixel[3*x+1] = piSrcPixel[4*x+1] * fltCvtFactor; + pfltDstPixel[3*x+2] = piSrcPixel[4*x+2] * fltCvtFactor; + } + } + + return WMP_errSuccess; +} + + + +ERR RGB96Float_RGB96Fixed(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX3 = 3 * pRect->Width; // 3 == R, G, B + const float fltCvtFactor = (float) (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + I32 *piDstPixel = (I32*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidthX3; x++) + piDstPixel[x] = (I32)(pfltSrcPixel[x] * fltCvtFactor + 0.5F); + } + + return WMP_errSuccess; +} + + +ERR RGB96Float_RGB128Fixed(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = (float) (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + assert(iWidth > 2); // Otherwise, we corrupt source data in inner loop + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + I32 *piDstPixel = (I32*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + piDstPixel[4*x] = (I32)(pfltSrcPixel[3*x] * fltCvtFactor + 0.5F); + piDstPixel[4*x+1] = (I32)(pfltSrcPixel[3*x+1] * fltCvtFactor + 0.5F); + piDstPixel[4*x+2] = (I32)(pfltSrcPixel[3*x+2] * fltCvtFactor + 0.5F); + piDstPixel[4*x+3] = 0; // Zero out the alpha channel + } + } + + return WMP_errSuccess; +} + + +ERR RGB96Float_RGB128Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + assert(iWidth > 2); // Otherwise, we corrupt source data in inner loop + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)pfltDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + pfltDstPixel[4*x] = pfltSrcPixel[3*x]; + pfltDstPixel[4*x+1] = pfltSrcPixel[3*x+1]; + pfltDstPixel[4*x+2] = pfltSrcPixel[3*x+2]; + pfltDstPixel[4*x+3] = 0.0F; // Zero out the alpha channel + } + } + + return WMP_errSuccess; +} + + +ERR RGB128Float_RGB96Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + pfltDstPixel[3*x] = pfltSrcPixel[4*x]; + pfltDstPixel[3*x+1] = pfltSrcPixel[4*x+1]; + pfltDstPixel[3*x+2] = pfltSrcPixel[4*x+2]; + } + } + + return WMP_errSuccess; +} + + +ERR RGB48Half_RGB64Half(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + assert(iWidth > 2); // Otherwise, we corrupt source data in inner loop + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)piDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + piDstPixel[4*x] = piSrcPixel[3*x]; + piDstPixel[4*x+1] = piSrcPixel[3*x+1]; + piDstPixel[4*x+2] = piSrcPixel[3*x+2]; + piDstPixel[4*x+3] = 0; // Zero out the alpha channel + } + } + + return WMP_errSuccess; +} + + +ERR RGB64Half_RGB48Half(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const short *piSrcPixel = (I16*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + piDstPixel[3*x] = piSrcPixel[4*x]; + piDstPixel[3*x+1] = piSrcPixel[4*x+1]; + piDstPixel[3*x+2] = piSrcPixel[4*x+2]; + } + } + + return WMP_errSuccess; +} + + +ERR BGR24_BGR32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + assert(iWidth > 2); // Otherwise, we corrupt source data in inner loop + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + U8 *piDstPixel = pb + cbStride*y; + const U8 *piSrcPixel = piDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + piDstPixel[4*x] = piSrcPixel[3*x]; + piDstPixel[4*x+1] = piSrcPixel[3*x+1]; + piDstPixel[4*x+2] = piSrcPixel[3*x+2]; + piDstPixel[4*x+3] = 0; // Zero out the alpha channel + } + } + + return WMP_errSuccess; +} + + +ERR BGR32_BGR24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = pb + cbStride*y; + const U8 *piSrcPixel = piDstPixel; + + for (x = 0; x < iWidth; x++) + { + piDstPixel[3*x] = piSrcPixel[4*x]; + piDstPixel[3*x+1] = piSrcPixel[4*x+1]; + piDstPixel[3*x+2] = piSrcPixel[4*x+2]; + } + } + + return WMP_errSuccess; +} + + +ERR Gray32Fixed_Gray32Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const I32 *piSrcPixel = (I32*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + pfltDstPixel[x] = piSrcPixel[x] * fltCvtFactor; + } + + return WMP_errSuccess; +} + + +ERR Gray32Float_Gray32Fixed(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = (float) (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + I32 *piDstPixel = (I32*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + piDstPixel[x] = (I32)(pfltSrcPixel[x] * fltCvtFactor + 0.5F); + } + + return WMP_errSuccess; +} + + + +ERR Gray16Fixed_Gray32Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + pfltDstPixel[x] = piSrcPixel[x] * fltCvtFactor; + } + + return WMP_errSuccess; +} + + +ERR Gray32Float_Gray16Fixed(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = (float) (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + piDstPixel[x] = (I16)(pfltSrcPixel[x] * fltCvtFactor + 0.5F); + } + + return WMP_errSuccess; +} + + +ERR RGB48Fixed_RGB96Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX3 = 3 * pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = iWidthX3 - 1; x >= 0; x--) + pfltDstPixel[x] = piSrcPixel[x] * fltCvtFactor; + } + + return WMP_errSuccess; +} + + +ERR RGB96Float_RGB48Fixed(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX3 = 3 * pRect->Width; + const float fltCvtFactor = (float)(1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidthX3; x++) + piDstPixel[x] = (I16)(pfltSrcPixel[x] * fltCvtFactor + 0.5F); + } + + return WMP_errSuccess; +} + + +ERR RGB64Fixed_RGB96Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + pfltDstPixel[3*x] = piSrcPixel[4*x] * fltCvtFactor; + pfltDstPixel[3*x+1] = piSrcPixel[4*x+1] * fltCvtFactor; + pfltDstPixel[3*x+2] = piSrcPixel[4*x+2] * fltCvtFactor; + } + } + + return WMP_errSuccess; +} + + +ERR RGB96Float_RGB64Fixed(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = (float)(1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + piDstPixel[4*x] = (I16)(pfltSrcPixel[3*x] * fltCvtFactor + 0.5F); + piDstPixel[4*x+1] = (I16)(pfltSrcPixel[3*x+1] * fltCvtFactor + 0.5F); + piDstPixel[4*x+2] = (I16)(pfltSrcPixel[3*x+2] * fltCvtFactor + 0.5F); + piDstPixel[4*x+3] = 0; // Zero out the alpha channel + } + } + + return WMP_errSuccess; +} + + +ERR RGBA64Fixed_RGBA128Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX4 = 4 * pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = iWidthX4 - 1; x >= 0; x--) + pfltDstPixel[x] = piSrcPixel[x] * fltCvtFactor; + } + + return WMP_errSuccess; +} + + + +ERR RGBA128Float_RGBA64Fixed(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX4 = 4 * pRect->Width; + const float fltCvtFactor = (float)(1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidthX4; x++) + piDstPixel[x] = (I16)(pfltSrcPixel[x] * fltCvtFactor + 0.5F); + } + + return WMP_errSuccess; +} + + + +ERR RGBE_RGB96Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + float *pfltDstPixel = (float*)(pb + cbStride*y); + const U8 *piSrcPixel = (U8*)pfltDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + // First read the exponent + const U8 rawExp = piSrcPixel[4*x+3]; + + if (0 == rawExp) + { + pfltDstPixel[3*x] = 0.0F; + pfltDstPixel[3*x+1] = 0.0F; + pfltDstPixel[3*x+2] = 0.0F; + } + else + { + const I32 adjExp = (I32)rawExp - 128 - 8; // Can be negative + float fltExp; + + if (adjExp > -32 && adjExp < 32) + { + fltExp = (float) (((U32)1) << abs(adjExp)); + if (adjExp < 0) + fltExp = 1.0F / fltExp; + } + else + { + fltExp = (float)ldexp(1.0F, adjExp); + } + + pfltDstPixel[3*x] = piSrcPixel[4*x] * fltExp; + pfltDstPixel[3*x + 1] = piSrcPixel[4*x + 1] * fltExp; + pfltDstPixel[3*x + 2] = piSrcPixel[4*x + 2] * fltExp; + } + } + } + + return WMP_errSuccess; +} + + +ERR RGB96Float_RGBE(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + assert(iWidth > 2); // Otherwise, we corrupt source data in inner loop + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + // We clamp source RGB values at zero (don't allow negative numbers) + const float fltRed = max(pfltSrcPixel[3*x], 0.0F); + const float fltGreen = max(pfltSrcPixel[3*x+1], 0.0F); + const float fltBlue = max(pfltSrcPixel[3*x+2], 0.0F); + float fltMaxPos = fltRed; + + if (fltGreen > fltMaxPos) + fltMaxPos = fltGreen; + + if (fltBlue > fltMaxPos) + fltMaxPos = fltBlue; + + if (fltMaxPos < 1e-32) + { + piDstPixel[4*x] = 0; // R + piDstPixel[4*x+1] = 0; // G + piDstPixel[4*x+2] = 0; // B + piDstPixel[4*x+3] = 0; // E + } + else + { + int e; + const float fltScale = (float)frexp(fltMaxPos, &e) * 256 / fltMaxPos; + + // rounding SHOULD NOT be added - it has the potential to roll over to zero (and yes, 256 is the correct multiplier above) + piDstPixel[4*x] = (U8)(fltRed * fltScale); // R + piDstPixel[4*x+1] = (U8)(fltGreen * fltScale); // G + piDstPixel[4*x+2] = (U8)(fltBlue * fltScale); // B + piDstPixel[4*x+3] = (U8)(e + 128); // E + } + } + } + + return WMP_errSuccess; +} + + +ERR RGBA64Half_RGBA128Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX4 = 4 * pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + U32 *pfltDstPixel = (U32*)(pb + cbStride*y); // It's really float, but use U32 ptr + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = iWidthX4 - 1; x >= 0; x--) + pfltDstPixel[x] = Convert_Half_To_Float(piSrcPixel[x]); + } + + return WMP_errSuccess; +} + + +ERR RGBA128Float_RGBA64Half(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX4 = 4 * pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidthX4; x++) + piDstPixel[x] = Convert_Float_To_Half(pfltSrcPixel[x]); + } + + return WMP_errSuccess; +} + + +ERR RGB64Half_RGB96Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + U32 *pfltDstPixel = (U32*)(pb + cbStride*y); // It's really float, but use U32 ptr + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + pfltDstPixel[3*x] = Convert_Half_To_Float(piSrcPixel[4*x]); + pfltDstPixel[3*x+1] = Convert_Half_To_Float(piSrcPixel[4*x+1]); + pfltDstPixel[3*x+2] = Convert_Half_To_Float(piSrcPixel[4*x+2]); + } + } + + return WMP_errSuccess; +} + + +ERR RGB96Float_RGB64Half(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + piDstPixel[4*x] = Convert_Float_To_Half(pfltSrcPixel[3*x]); + piDstPixel[4*x+1] = Convert_Float_To_Half(pfltSrcPixel[3*x+1]); + piDstPixel[4*x+2] = Convert_Float_To_Half(pfltSrcPixel[3*x+2]); + piDstPixel[4*x+3] = 0; // Zero out the alpha channel + } + } + + return WMP_errSuccess; +} + + +ERR RGB48Half_RGB96Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX3 = 3*pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + U32 *pfltDstPixel = (U32*)(pb + cbStride*y); // It's really float, but use U32 ptr + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = iWidthX3 - 1; x >= 0; x--) + pfltDstPixel[x] = Convert_Half_To_Float(piSrcPixel[x]); + } + + return WMP_errSuccess; +} + + +ERR RGB96Float_RGB48Half(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX3 = 3*pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidthX3; x++) + piDstPixel[x] = Convert_Float_To_Half(pfltSrcPixel[x]); + } + + return WMP_errSuccess; +} + + +ERR Gray16Half_Gray32Float(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + U32 *pfltDstPixel = (U32*)(pb + cbStride*y); // It's really float, but use U32 ptr + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + pfltDstPixel[x] = Convert_Half_To_Float(piSrcPixel[x]); + } + + return WMP_errSuccess; +} + + +ERR Gray32Float_Gray16Half(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + I16 *piDstPixel = (I16*)(pb + cbStride*y); + const float *pfltSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + piDstPixel[x] = Convert_Float_To_Half(pfltSrcPixel[x]); + } + + return WMP_errSuccess; +} + +ERR RGB555_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + U8 *piDstPixel = (pb + cbStride*y); + const U16 *piSrcPixel = (U16*)piDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + const U16 v = piSrcPixel[x]; + const unsigned int r = ((v >> 10) & 0x1f); + const unsigned int g = ((v >> 5) & 0x1f); + const unsigned int b = (v & 0x1f); + + piDstPixel[3*x] = (U8)(r << 3); // R + piDstPixel[3*x+1] = (U8)(g << 3); // G + piDstPixel[3*x+2] = (U8)(b << 3); // B + } + } + + return WMP_errSuccess; +} + + +ERR RGB101010_RGB48(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + U16 *piDstPixel = (U16*)(pb + cbStride*y); + const U32 *piSrcPixel = (U32*)piDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + const U32 v = piSrcPixel[x]; + const unsigned int r = ((v >> 20) & 0x3FF); + const unsigned int g = ((v >> 10) & 0x3FF); + const unsigned int b = (v & 0x3FF); + + piDstPixel[3*x] = (U16)(r << 6); // R + piDstPixel[3*x+1] = (U16)(g << 6); // G + piDstPixel[3*x+2] = (U16)(b << 6); // B + } + } + + return WMP_errSuccess; +} + + +ERR RGB24_RGB555(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U16 *piDstPixel = (U16*)(pb + cbStride*y); + const U8 *piSrcPixel = (U8*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const unsigned int r = piSrcPixel[3*x]; + const unsigned int g = piSrcPixel[3*x+1]; + const unsigned int b = piSrcPixel[3*x+2]; + + piDstPixel[x] = (U16) ( + ((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3)); + } + } + + return WMP_errSuccess; +} + + + +ERR RGB48_RGB101010(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U32 *piDstPixel = (U32*)(pb + cbStride*y); + const U16 *piSrcPixel = (U16*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const unsigned int r = piSrcPixel[3*x]; + const unsigned int g = piSrcPixel[3*x+1]; + const unsigned int b = piSrcPixel[3*x+2]; + + piDstPixel[x] = (3 << 30) | // For compatibility with D3D's 2-10-10-10 format. + ((r & 0x0000FFC0) << 14) | + ((g & 0x0000FFC0) << 4) | + (b >> 6); + } + } + + return WMP_errSuccess; +} + + + +ERR RGB565_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + U8 *piDstPixel = (pb + cbStride*y); + const U16 *piSrcPixel = (U16*)piDstPixel; + + for (x = iWidth - 1; x >= 0; x--) + { + const U16 v = piSrcPixel[x]; + const unsigned int r = ((v >> 11) & 0x1f); + const unsigned int g = ((v >> 5) & 0x3f); + const unsigned int b = (v & 0x1f); + + piDstPixel[3*x] = (U8)(r << 3); // R + piDstPixel[3*x+1] = (U8)(g << 2); // G + piDstPixel[3*x+2] = (U8)(b << 3); // B + } + } + + return WMP_errSuccess; +} + + + +ERR RGB24_RGB565(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U16 *piDstPixel = (U16*)(pb + cbStride*y); + const U8 *piSrcPixel = (U8*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const unsigned int r = piSrcPixel[3*x]; + const unsigned int g = piSrcPixel[3*x+1]; + const unsigned int b = piSrcPixel[3*x+2]; + + piDstPixel[x] = (U16) ( + ((r & 0xF8) << 8) | + ((g & 0xFC) << 3) | + (b >> 3)); + } + } + + return WMP_errSuccess; +} + + +ERR RGBA32_BGRA32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidthX4 = 4 * pRect->Width; // 4 == R, G, B, A + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piPixel = (U8*)(pb + cbStride*y); + + for (x = 0; x < iWidthX4; x += 4) + { + // Swap R and B + U8 bTemp = piPixel[x]; + piPixel[x] = piPixel[x+2]; + piPixel[x+2] = bTemp; + } + } + + return WMP_errSuccess; +} + + +ERR BGRA32_RGBA32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + return RGBA32_BGRA32(pFC, pRect, pb, cbStride); +} + + +ERR BlackWhite_Gray8(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + Bool bBlackWhite = pFC->pDecoder->WMP.wmiSCP.bBlackWhite; + I32 y; + + // Stride is assumed to be same for src/dst + for (y = iHeight - 1; y >= 0; y--) + { + I32 x; + I32 n; + U8 *piDstPixel = (pb + cbStride*y); + const U8 *piSrcPixel = (U8*)piDstPixel; + + if (iWidth % 8 != 0) + { + const U8 v = piSrcPixel[iWidth / 8]; + + for (n = 0; n < iWidth % 8; n++) + { + piDstPixel[iWidth/8*8+n] = (((v >> (7 - n)) & 0x1) != 0) ^ bBlackWhite ? 0xFF : 0x00; + } + } + + for (x = iWidth / 8 - 1; x >= 0; x--) + { + const U8 v = piSrcPixel[x]; + + for (n = 0; n < 8; n++) + { + piDstPixel[8*x+n] = (((v >> (7 - n)) & 0x1) != 0) ^ bBlackWhite ? 0xFF : 0x00; + } + } + } + + return WMP_errSuccess; +} + + +ERR Gray16_Gray8(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + I32 i = 0, j = 0; + + UNREFERENCED_PARAMETER( pFC ); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = 0; j < pRect->Width; ++j) + { + U16 v = ((U16*)pb)[j]; + + pb[j] = v >> 8; + } + + pb += cbStride; + } + + return WMP_errSuccess; +} + +ERR RGB48_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const U16 *piSrcPixel = (U16*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const U16 r = piSrcPixel[3*x]; + const U16 g = piSrcPixel[3*x+1]; + const U16 b = piSrcPixel[3*x+2]; + + piDstPixel[3*x] = r >> 8; + piDstPixel[3*x+1] = g >> 8; + piDstPixel[3*x+2] = b >> 8; + } + } + + return WMP_errSuccess; +} + +ERR RGBA64_RGBA32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const U16 *piSrcPixel = (U16*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const U16 r = piSrcPixel[4*x]; + const U16 g = piSrcPixel[4*x+1]; + const U16 b = piSrcPixel[4*x+2]; + const U16 a = piSrcPixel[4*x+3]; + + piDstPixel[4*x] = r >> 8; + piDstPixel[4*x+1] = g >> 8; + piDstPixel[4*x+2] = b >> 8; + piDstPixel[4*x+3] = a >> 8; + } + } + + return WMP_errSuccess; +} + +ERR Gray32Float_Gray8(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const float *piSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const float v = piSrcPixel[x]; + + piDstPixel[x] = Convert_Float_To_U8(v); + } + } + + return WMP_errSuccess; +} + +ERR RGB96Float_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const float *piSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const float r = piSrcPixel[3*x]; + const float g = piSrcPixel[3*x+1]; + const float b = piSrcPixel[3*x+2]; + + piDstPixel[3*x] = Convert_Float_To_U8(r); + piDstPixel[3*x+1] = Convert_Float_To_U8(g); + piDstPixel[3*x+2] = Convert_Float_To_U8(b); + } + } + + return WMP_errSuccess; +} + +ERR RGB128Float_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const float *piSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const float r = piSrcPixel[4*x]; + const float g = piSrcPixel[4*x+1]; + const float b = piSrcPixel[4*x+2]; + + piDstPixel[3*x] = Convert_Float_To_U8(r); + piDstPixel[3*x+1] = Convert_Float_To_U8(g); + piDstPixel[3*x+2] = Convert_Float_To_U8(b); + } + } + + return WMP_errSuccess; +} + +ERR RGBA128Float_RGBA32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const float *piSrcPixel = (float*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const float r = piSrcPixel[4*x]; + const float g = piSrcPixel[4*x+1]; + const float b = piSrcPixel[4*x+2]; + const float a = piSrcPixel[4*x+3]; + + piDstPixel[4*x] = Convert_Float_To_U8(r); + piDstPixel[4*x+1] = Convert_Float_To_U8(g); + piDstPixel[4*x+2] = Convert_Float_To_U8(b); + piDstPixel[4*x+3] = Convert_AlphaFloat_To_U8(a); + } + } + + return WMP_errSuccess; +} + +ERR Gray16Fixed_Gray8(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + piDstPixel[x] = Convert_Float_To_U8(piSrcPixel[x] * fltCvtFactor); + } + } + + return WMP_errSuccess; +} + +ERR Gray32Fixed_Gray8(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const I32 *piSrcPixel = (I32*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + piDstPixel[x] = Convert_Float_To_U8(piSrcPixel[x] * fltCvtFactor); + } + } + + return WMP_errSuccess; +} + +ERR RGB48Fixed_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + pfltDstPixel[3*x] = Convert_Float_To_U8(piSrcPixel[3*x] * fltCvtFactor); + pfltDstPixel[3*x+1] = Convert_Float_To_U8(piSrcPixel[3*x+1] * fltCvtFactor); + pfltDstPixel[3*x+2] = Convert_Float_To_U8(piSrcPixel[3*x+2] * fltCvtFactor); + } + } + + return WMP_errSuccess; +} + +ERR RGB64Fixed_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + pfltDstPixel[3*x] = Convert_Float_To_U8(piSrcPixel[4*x] * fltCvtFactor); + pfltDstPixel[3*x+1] = Convert_Float_To_U8(piSrcPixel[4*x+1] * fltCvtFactor); + pfltDstPixel[3*x+2] = Convert_Float_To_U8(piSrcPixel[4*x+2] * fltCvtFactor); + } + } + + return WMP_errSuccess; +} + +ERR RGB96Fixed_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const I32 *piSrcPixel = (I32*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + pfltDstPixel[3*x] = Convert_Float_To_U8(piSrcPixel[3*x] * fltCvtFactor); + pfltDstPixel[3*x+1] = Convert_Float_To_U8(piSrcPixel[3*x+1] * fltCvtFactor); + pfltDstPixel[3*x+2] = Convert_Float_To_U8(piSrcPixel[3*x+2] * fltCvtFactor); + } + } + + return WMP_errSuccess; +} + +ERR RGB128Fixed_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const I32 *piSrcPixel = (I32*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + pfltDstPixel[3*x] = Convert_Float_To_U8(piSrcPixel[4*x] * fltCvtFactor); + pfltDstPixel[3*x+1] = Convert_Float_To_U8(piSrcPixel[4*x+1] * fltCvtFactor); + pfltDstPixel[3*x+2] = Convert_Float_To_U8(piSrcPixel[4*x+2] * fltCvtFactor); + } + } + + return WMP_errSuccess; +} + +ERR RGBA64Fixed_RGBA32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 13); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const I16 *piSrcPixel = (I16*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + pfltDstPixel[4*x] = Convert_Float_To_U8(piSrcPixel[4*x] * fltCvtFactor); + pfltDstPixel[4*x+1] = Convert_Float_To_U8(piSrcPixel[4*x+1] * fltCvtFactor); + pfltDstPixel[4*x+2] = Convert_Float_To_U8(piSrcPixel[4*x+2] * fltCvtFactor); + pfltDstPixel[4*x+3] = Convert_AlphaFloat_To_U8(piSrcPixel[4*x+3] * fltCvtFactor); + } + } + + return WMP_errSuccess; +} + +ERR RGBA128Fixed_RGBA32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + const float fltCvtFactor = 1.0F / (1 << 24); + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const I32 *piSrcPixel = (I32*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + pfltDstPixel[4*x] = Convert_Float_To_U8(piSrcPixel[4*x] * fltCvtFactor); + pfltDstPixel[4*x+1] = Convert_Float_To_U8(piSrcPixel[4*x+1] * fltCvtFactor); + pfltDstPixel[4*x+2] = Convert_Float_To_U8(piSrcPixel[4*x+2] * fltCvtFactor); + pfltDstPixel[4*x+3] = Convert_AlphaFloat_To_U8(piSrcPixel[4*x+3] * fltCvtFactor); + } + } + + return WMP_errSuccess; +} + +ERR Gray16Half_Gray8(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const U16 *piSrcPixel = (U16*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const U32 v = Convert_Half_To_Float(piSrcPixel[x]); + + piDstPixel[x] = Convert_Float_To_U8(*(float*)&v); + } + } + + return WMP_errSuccess; +} + +ERR RGB48Half_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const U16 *piSrcPixel = (U16*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + const U32 r = Convert_Half_To_Float(piSrcPixel[3*x]); + const U32 g = Convert_Half_To_Float(piSrcPixel[3*x+1]); + const U32 b = Convert_Half_To_Float(piSrcPixel[3*x+2]); + + pfltDstPixel[3*x] = Convert_Float_To_U8(*(float*)&r); + pfltDstPixel[3*x+1] = Convert_Float_To_U8(*(float*)&g); + pfltDstPixel[3*x+2] = Convert_Float_To_U8(*(float*)&b); + } + } + + return WMP_errSuccess; +} + +ERR RGB64Half_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const U16 *piSrcPixel = (U16*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + const U32 r = Convert_Half_To_Float(piSrcPixel[4*x]); + const U32 g = Convert_Half_To_Float(piSrcPixel[4*x+1]); + const U32 b = Convert_Half_To_Float(piSrcPixel[4*x+2]); + + pfltDstPixel[3*x] = Convert_Float_To_U8(*(float*)&r); + pfltDstPixel[3*x+1] = Convert_Float_To_U8(*(float*)&g); + pfltDstPixel[3*x+2] = Convert_Float_To_U8(*(float*)&b); + } + } + + return WMP_errSuccess; +} + +ERR RGBA64Half_RGBA32(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *pfltDstPixel = (U8*)(pb + cbStride*y); + const U16 *piSrcPixel = (U16*)pfltDstPixel; + + for (x = 0; x < iWidth; x++) + { + const U32 r = Convert_Half_To_Float(piSrcPixel[4*x]); + const U32 g = Convert_Half_To_Float(piSrcPixel[4*x+1]); + const U32 b = Convert_Half_To_Float(piSrcPixel[4*x+2]); + const U32 a = Convert_Half_To_Float(piSrcPixel[4*x+3]); + + pfltDstPixel[4*x] = Convert_Float_To_U8(*(float*)&r); + pfltDstPixel[4*x+1] = Convert_Float_To_U8(*(float*)&g); + pfltDstPixel[4*x+2] = Convert_Float_To_U8(*(float*)&b); + pfltDstPixel[4*x+3] = Convert_AlphaFloat_To_U8(*(float*)&a); + } + } + + return WMP_errSuccess; +} + +ERR RGB101010_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + const I32 iHeight = pRect->Height; + const I32 iWidth = pRect->Width; + I32 y; + + UNREFERENCED_PARAMETER( pFC ); + + // Stride is assumed to be same for src/dst + for (y = 0; y < iHeight; y++) + { + I32 x; + U8 *piDstPixel = (U8*)(pb + cbStride*y); + const U32 *piSrcPixel = (U32*)piDstPixel; + + for (x = 0; x < iWidth; x++) + { + const U32 v = piSrcPixel[x]; + const unsigned int r = ((v >> 20) & 0x3FF); + const unsigned int g = ((v >> 10) & 0x3FF); + const unsigned int b = (v & 0x3FF); + + piDstPixel[3*x] = (U8) (r >> 2); + piDstPixel[3*x+1] = (U8) (g >> 2); + piDstPixel[3*x+2] = (U8) (b >> 2); + } + } + + return WMP_errSuccess; +} + +ERR RGBE_RGB24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + I32 i = 0, j = 0; + + UNREFERENCED_PARAMETER( pFC ); + + for (i = 0; i < pRect->Height; ++i) + { + for (j = 0; j < pRect->Width; j++) + { + // First read the exponent + const U8 rawExp = pb[4*j+3]; + + if (0 == rawExp) + { + pb[3*j] = 0; + pb[3*j+1] = 0; + pb[3*j+2] = 0; + } + else + { + const I32 adjExp = (I32)rawExp - 128 - 8; // Can be negative + float fltExp; + + if (adjExp > -32 && adjExp < 32) + { + fltExp = (float) (((U32)1) << abs(adjExp)); + if (adjExp < 0) + fltExp = 1.0F / fltExp; + } + else + { + fltExp = (float)ldexp(1.0F, adjExp); + } + + pb[3*j] = Convert_Float_To_U8(pb[4*j] * fltExp); + pb[3*j + 1] = Convert_Float_To_U8(pb[4*j + 1] * fltExp); + pb[3*j + 2] = Convert_Float_To_U8(pb[4*j + 2] * fltExp); + } + } + + pb += cbStride; + } + + return WMP_errSuccess; +} + +//================================================================ +typedef struct tagPKPixelConverterInfo +{ + const PKPixelFormatGUID* pGUIDPixFmtFrom; + const PKPixelFormatGUID* pGUIDPixFmtTo; + + ERR (*Convert)(PKFormatConverter*, const PKRect*, U8*, U32); +} PKPixelConverterInfo; + +static PKPixelConverterInfo s_pcInfo[] = { + {&GUID_PKPixelFormat24bppRGB, &GUID_PKPixelFormat24bppBGR, RGB24_BGR24}, // Fwd + {&GUID_PKPixelFormat24bppBGR, &GUID_PKPixelFormat24bppRGB, BGR24_RGB24}, // Rev + {&GUID_PKPixelFormat24bppRGB, &GUID_PKPixelFormat32bppBGR, RGB24_BGR32}, // Fwd + {&GUID_PKPixelFormat32bppBGR, &GUID_PKPixelFormat24bppRGB, BGR32_RGB24}, // Rev + + // The following are not to be exposed when building the Adobe Photoshop plugin +#ifndef ADOBE_PS_PLUGIN + {&GUID_PKPixelFormat24bppRGB, &GUID_PKPixelFormat8bppGray, RGB24_Gray8}, // Fwd + {&GUID_PKPixelFormat8bppGray, &GUID_PKPixelFormat24bppRGB, Gray8_RGB24}, // Rev + {&GUID_PKPixelFormat24bppBGR, &GUID_PKPixelFormat8bppGray, BGR24_Gray8}, // Fwd + {&GUID_PKPixelFormat8bppGray, &GUID_PKPixelFormat24bppBGR, Gray8_BGR24}, // Rev +#endif // ADOBE_PS_PLUGIN + + {&GUID_PKPixelFormat128bppRGBAFixedPoint, &GUID_PKPixelFormat128bppRGBAFloat, RGBA128Fixed_RGBA128Float}, // Fwd + {&GUID_PKPixelFormat128bppRGBAFloat, &GUID_PKPixelFormat128bppRGBAFixedPoint, RGBA128Float_RGBA128Fixed}, // Rev + {&GUID_PKPixelFormat96bppRGBFixedPoint, &GUID_PKPixelFormat96bppRGBFloat, RGB96Fixed_RGB96Float}, // Fwd + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat96bppRGBFixedPoint, RGB96Float_RGB96Fixed}, // Rev + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat128bppRGBFloat, RGB96Float_RGB128Float}, // Fwd + {&GUID_PKPixelFormat128bppRGBFloat, &GUID_PKPixelFormat96bppRGBFloat, RGB128Float_RGB96Float}, // Rev + {&GUID_PKPixelFormat96bppRGBFixedPoint, &GUID_PKPixelFormat128bppRGBFixedPoint, RGB96Float_RGB128Float}, // Fwd + {&GUID_PKPixelFormat128bppRGBFixedPoint, &GUID_PKPixelFormat96bppRGBFixedPoint, RGB128Float_RGB96Float}, // Rev + {&GUID_PKPixelFormat64bppRGBHalf, &GUID_PKPixelFormat48bppRGBHalf, RGB64Half_RGB48Half}, // Fwd + {&GUID_PKPixelFormat48bppRGBHalf, &GUID_PKPixelFormat64bppRGBHalf, RGB48Half_RGB64Half}, // Rev + {&GUID_PKPixelFormat64bppRGBFixedPoint, &GUID_PKPixelFormat48bppRGBFixedPoint, RGB64Half_RGB48Half}, // Fwd + {&GUID_PKPixelFormat48bppRGBFixedPoint, &GUID_PKPixelFormat64bppRGBFixedPoint, RGB48Half_RGB64Half}, // Rev + {&GUID_PKPixelFormat32bppBGR, &GUID_PKPixelFormat24bppBGR, BGR32_BGR24}, // Fwd + {&GUID_PKPixelFormat24bppBGR, &GUID_PKPixelFormat32bppBGR, BGR24_BGR32}, // Rev + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat128bppRGBFixedPoint, RGB96Float_RGB128Fixed}, // Fwd + {&GUID_PKPixelFormat128bppRGBFixedPoint, &GUID_PKPixelFormat96bppRGBFloat, RGB128Fixed_RGB96Float}, // Rev + {&GUID_PKPixelFormat32bppGrayFixedPoint, &GUID_PKPixelFormat32bppGrayFloat, Gray32Fixed_Gray32Float}, // Fwd + {&GUID_PKPixelFormat32bppGrayFloat, &GUID_PKPixelFormat32bppGrayFixedPoint, Gray32Float_Gray32Fixed}, // Rev + {&GUID_PKPixelFormat16bppGrayFixedPoint, &GUID_PKPixelFormat32bppGrayFloat, Gray16Fixed_Gray32Float}, // Fwd + {&GUID_PKPixelFormat32bppGrayFloat, &GUID_PKPixelFormat16bppGrayFixedPoint, Gray32Float_Gray16Fixed}, // Rev + {&GUID_PKPixelFormat48bppRGBFixedPoint, &GUID_PKPixelFormat96bppRGBFloat, RGB48Fixed_RGB96Float}, // Fwd + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat48bppRGBFixedPoint, RGB96Float_RGB48Fixed}, // Rev + {&GUID_PKPixelFormat64bppRGBFixedPoint, &GUID_PKPixelFormat96bppRGBFloat, RGB64Fixed_RGB96Float}, // Fwd + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat64bppRGBFixedPoint, RGB96Float_RGB64Fixed}, // Rev + {&GUID_PKPixelFormat64bppRGBAFixedPoint, &GUID_PKPixelFormat128bppRGBAFloat, RGBA64Fixed_RGBA128Float}, // Fwd + {&GUID_PKPixelFormat128bppRGBAFloat, &GUID_PKPixelFormat64bppRGBAFixedPoint, RGBA128Float_RGBA64Fixed}, // Rev + {&GUID_PKPixelFormat32bppRGBE, &GUID_PKPixelFormat96bppRGBFloat, RGBE_RGB96Float}, // Fwd + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat32bppRGBE, RGB96Float_RGBE}, // Rev + {&GUID_PKPixelFormat64bppRGBAHalf, &GUID_PKPixelFormat128bppRGBAFloat, RGBA64Half_RGBA128Float}, // Fwd + {&GUID_PKPixelFormat128bppRGBAFloat, &GUID_PKPixelFormat64bppRGBAHalf, RGBA128Float_RGBA64Half}, // Rev + {&GUID_PKPixelFormat64bppRGBHalf, &GUID_PKPixelFormat96bppRGBFloat, RGB64Half_RGB96Float}, // Fwd + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat64bppRGBHalf, RGB96Float_RGB64Half}, // Rev + {&GUID_PKPixelFormat48bppRGBHalf, &GUID_PKPixelFormat96bppRGBFloat, RGB48Half_RGB96Float}, // Fwd + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat48bppRGBHalf, RGB96Float_RGB48Half}, // Rev + {&GUID_PKPixelFormat16bppGrayHalf, &GUID_PKPixelFormat32bppGrayFloat, Gray16Half_Gray32Float}, // Fwd + {&GUID_PKPixelFormat32bppGrayFloat, &GUID_PKPixelFormat16bppGrayHalf, Gray32Float_Gray16Half}, // Rev + {&GUID_PKPixelFormat16bppRGB555, &GUID_PKPixelFormat24bppRGB, RGB555_RGB24}, // Fwd + {&GUID_PKPixelFormat24bppRGB, &GUID_PKPixelFormat16bppRGB555, RGB24_RGB555}, // Rev + {&GUID_PKPixelFormat16bppRGB565, &GUID_PKPixelFormat24bppRGB, RGB565_RGB24}, // Fwd + {&GUID_PKPixelFormat24bppRGB, &GUID_PKPixelFormat16bppRGB565, RGB24_RGB565}, // Rev + {&GUID_PKPixelFormat32bppRGB101010, &GUID_PKPixelFormat48bppRGB, RGB101010_RGB48}, // Fwd + {&GUID_PKPixelFormat48bppRGB, &GUID_PKPixelFormat32bppRGB101010, RGB48_RGB101010}, // Rev + {&GUID_PKPixelFormat32bppRGBA, &GUID_PKPixelFormat32bppBGRA, RGBA32_BGRA32}, // Fwd + {&GUID_PKPixelFormat32bppBGRA, &GUID_PKPixelFormat32bppRGBA, BGRA32_RGBA32}, // Rev + {&GUID_PKPixelFormat32bppPRGBA, &GUID_PKPixelFormat32bppPBGRA, RGBA32_BGRA32}, // Fwd + {&GUID_PKPixelFormat32bppPBGRA, &GUID_PKPixelFormat32bppPRGBA, BGRA32_RGBA32}, // Rev + + // conversions to 8bppGray / 24bppRGB / 32bppRGBA + {&GUID_PKPixelFormatBlackWhite, &GUID_PKPixelFormat8bppGray, BlackWhite_Gray8}, + {&GUID_PKPixelFormat16bppGray, &GUID_PKPixelFormat8bppGray, Gray16_Gray8}, + {&GUID_PKPixelFormat48bppRGB, &GUID_PKPixelFormat24bppRGB, RGB48_RGB24}, + {&GUID_PKPixelFormat64bppRGBA, &GUID_PKPixelFormat32bppRGBA, RGBA64_RGBA32}, + {&GUID_PKPixelFormat32bppGrayFloat, &GUID_PKPixelFormat8bppGray, Gray32Float_Gray8}, + {&GUID_PKPixelFormat96bppRGBFloat, &GUID_PKPixelFormat24bppRGB, RGB96Float_RGB24}, + {&GUID_PKPixelFormat128bppRGBFloat, &GUID_PKPixelFormat24bppRGB, RGB128Float_RGB24}, + {&GUID_PKPixelFormat128bppRGBAFloat, &GUID_PKPixelFormat32bppRGBA, RGBA128Float_RGBA32}, + {&GUID_PKPixelFormat16bppGrayFixedPoint, &GUID_PKPixelFormat8bppGray, Gray16Fixed_Gray8}, + {&GUID_PKPixelFormat32bppGrayFixedPoint, &GUID_PKPixelFormat8bppGray, Gray32Fixed_Gray8}, + {&GUID_PKPixelFormat48bppRGBFixedPoint, &GUID_PKPixelFormat24bppRGB, RGB48Fixed_RGB24}, + {&GUID_PKPixelFormat64bppRGBFixedPoint, &GUID_PKPixelFormat24bppRGB, RGB64Fixed_RGB24}, + {&GUID_PKPixelFormat96bppRGBFixedPoint, &GUID_PKPixelFormat24bppRGB, RGB96Fixed_RGB24}, + {&GUID_PKPixelFormat128bppRGBFixedPoint, &GUID_PKPixelFormat24bppRGB, RGB128Fixed_RGB24}, + {&GUID_PKPixelFormat64bppRGBAFixedPoint, &GUID_PKPixelFormat32bppRGBA, RGBA64Fixed_RGBA32}, + {&GUID_PKPixelFormat128bppRGBAFixedPoint, &GUID_PKPixelFormat32bppRGBA, RGBA128Fixed_RGBA32}, + {&GUID_PKPixelFormat16bppGrayHalf, &GUID_PKPixelFormat8bppGray, Gray16Half_Gray8}, + {&GUID_PKPixelFormat48bppRGBHalf, &GUID_PKPixelFormat24bppRGB, RGB48Half_RGB24}, + {&GUID_PKPixelFormat64bppRGBHalf, &GUID_PKPixelFormat24bppRGB, RGB64Half_RGB24}, + {&GUID_PKPixelFormat64bppRGBAHalf, &GUID_PKPixelFormat32bppRGBA, RGBA64Half_RGBA32}, + {&GUID_PKPixelFormat32bppRGB101010, &GUID_PKPixelFormat24bppRGB, RGB101010_RGB24}, + {&GUID_PKPixelFormat32bppRGBE, &GUID_PKPixelFormat24bppRGB, RGBE_RGB24} +}; + +/* auxiliary data structure and hack to support valid encoding from/to configurations that +// don't actually require any color conversion. This is a conservative approach, where we +// include as few formats as necessary to encode situations that we're currently aware of. +*/ +typedef struct tagPKPixelConverter2Info +{ + const PKPixelFormatGUID* pGUIDPixFmtFrom; + const PKPixelFormatGUID* pGUIDPixFmtTo; + +} PKPixelConverter2Info; + +static PKPixelConverter2Info s_pcInfo2[] = { + // This allows us to view an RGBA input file as RGB, for when we create a planar alpha file + {&GUID_PKPixelFormat128bppRGBFloat, &GUID_PKPixelFormat128bppRGBAFloat}, + // 16- and 32-bpp RGB input files are given the "DontCare" GUID, so the next three + // from/to combinations are ok, and allowed on encoding: + {&GUID_PKPixelFormatDontCare, &GUID_PKPixelFormat16bppRGB555}, + {&GUID_PKPixelFormatDontCare, &GUID_PKPixelFormat16bppRGB565}, + {&GUID_PKPixelFormatDontCare, &GUID_PKPixelFormat32bppBGRA} +}; + +ERR PKFormatConverter_Initialize(PKFormatConverter* pFC, PKImageDecode* pID, char *pExt, PKPixelFormatGUID enPF) +{ + ERR err; + PKPixelFormatGUID enPFFrom; + + Call(pID->GetPixelFormat(pID, &enPFFrom)); + Call(PKFormatConverter_InitializeConvert(pFC, enPFFrom, pExt, enPF)); + + pFC->pDecoder = pID; + +Cleanup: + return err; +} + + +extern int PKStrnicmp(const char* s1, const char* s2, size_t c); + +ERR PKFormatConverter_InitializeConvert(PKFormatConverter* pFC, const PKPixelFormatGUID enPFFrom, + char *pExt, PKPixelFormatGUID enPFTo) +{ + ERR err = WMP_errSuccess; + + //================================ + pFC->enPixelFormat = enPFTo; + + if (pExt != NULL && IsEqualGUID(&enPFTo, &GUID_PKPixelFormat24bppRGB) && + 0 == PKStrnicmp(pExt, ".bmp", strlen(pExt))) + enPFTo = GUID_PKPixelFormat24bppBGR; + if (pExt != NULL && (0 == PKStrnicmp(pExt, ".tif", strlen(pExt)) || 0 == PKStrnicmp(pExt, ".tiff", strlen(pExt)))) + { + if (IsEqualGUID(&enPFTo, &GUID_PKPixelFormat32bppBGRA)) + enPFTo = GUID_PKPixelFormat32bppRGBA; + if (IsEqualGUID(&enPFTo, &GUID_PKPixelFormat32bppPBGRA)) + enPFTo = GUID_PKPixelFormat32bppPRGBA; + } + + //================================ + if (!IsEqualGUID(&enPFFrom, &enPFTo)) + { + size_t i = 0; + for (i = 0; i < sizeof2(s_pcInfo); ++i) + { + PKPixelConverterInfo* pPCI = s_pcInfo + i; + + if (IsEqualGUID(&enPFFrom, pPCI->pGUIDPixFmtFrom) && IsEqualGUID(&enPFTo, pPCI->pGUIDPixFmtTo)) + { + pFC->Convert= pPCI->Convert; + goto Cleanup; + } + } + // Bugfix to allow legitimate encoding from/to combinations that don't actually + // involve color conversions. + for (i = 0; i < sizeof2(s_pcInfo2); ++i) + { + PKPixelConverter2Info* pPCI = s_pcInfo2 + i; + + if (IsEqualGUID(&enPFFrom, pPCI->pGUIDPixFmtFrom) && IsEqualGUID(&enPFTo, pPCI->pGUIDPixFmtTo)) + { + goto Cleanup; + } + } + // If we failed the original check, and this bugfix check, then exit with error + Call(WMP_errUnsupportedFormat); + } + +Cleanup: + return err; +} + +ERR PKFormatConverter_EnumConversions(const PKPixelFormatGUID *pguidSourcePF, + const U32 iIndex, + const PKPixelFormatGUID **ppguidTargetPF) +{ + U32 iCurrIdx = 0; + U32 i; + ERR errResult = WMP_errIndexNotFound; + + *ppguidTargetPF = &GUID_PKPixelFormatDontCare; // Init return value + for (i = 0; i < sizeof2(s_pcInfo); i++) + { + if (IsEqualGUID(s_pcInfo[i].pGUIDPixFmtFrom, pguidSourcePF)) + { + if (iCurrIdx == iIndex) + { + // Found our target + errResult = WMP_errSuccess; + *ppguidTargetPF = s_pcInfo[i].pGUIDPixFmtTo; + break; + } + iCurrIdx += 1; + } + } + + return errResult; +} + +ERR PKFormatConverter_GetPixelFormat(PKFormatConverter* pFC, PKPixelFormatGUID* pPF) +{ + *pPF = pFC->enPixelFormat; + + return WMP_errSuccess; +} + +ERR PKFormatConverter_GetSourcePixelFormat(PKFormatConverter* pFC, PKPixelFormatGUID* pPF) +{ + return pFC->pDecoder->GetPixelFormat(pFC->pDecoder, pPF); +} + +ERR PKFormatConverter_GetSize(PKFormatConverter* pFC, I32* piWidth, I32* piHeight) +{ + return pFC->pDecoder->GetSize(pFC->pDecoder, piWidth, piHeight); +} + +ERR PKFormatConverter_GetResolution(PKFormatConverter* pFC, Float* pfrX, Float* pfrY) +{ + return pFC->pDecoder->GetResolution(pFC->pDecoder, pfrX, pfrY); +} + +ERR PKFormatConverter_Copy(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + ERR err = WMP_errSuccess; + + Call(pFC->pDecoder->Copy(pFC->pDecoder, pRect, pb, cbStride)); + Call(pFC->Convert(pFC, pRect, pb, cbStride)); + +Cleanup: + return err; +} + +ERR PKFormatConverter_Convert(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride) +{ + UNREFERENCED_PARAMETER( pFC ); + UNREFERENCED_PARAMETER( pRect ); + UNREFERENCED_PARAMETER( pb ); + UNREFERENCED_PARAMETER( cbStride ); + + return WMP_errSuccess; +} + +ERR PKFormatConverter_Release(PKFormatConverter** ppFC) +{ + ERR err = WMP_errSuccess; + + Call(PKFree((void **) ppFC)); + +Cleanup: + return err; +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGluePFC.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGluePFC.o new file mode 100644 index 0000000..709bc49 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRGluePFC.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.c b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.c new file mode 100644 index 0000000..020c324 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.c @@ -0,0 +1,905 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#include "JXRMeta.h" +#include "JXRGlue.h" + + + +// read and write big and little endian words/dwords from a buffer on both big and little endian cpu's +// with full buffer overflow checking + + + +ERR getbfcpy(U8* pbdest, const U8* pb, size_t cb, size_t ofs, U32 n) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + n > cb, WMP_errBufferOverflow); + memcpy(pbdest, &pb[ofs], n); +Cleanup: + return err; +} + + + +ERR getbfw(const U8* pb, size_t cb, size_t ofs, U16* pw) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + sizeof(U16) > cb, WMP_errBufferOverflow); + *pw = (U16)( pb[ofs] + ( pb[ofs + 1] << 8 ) ); +Cleanup: + return err; +} + + + +ERR getbfdw(const U8* pb, size_t cb, size_t ofs, U32* pdw) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + sizeof(U32) > cb, WMP_errBufferOverflow); + *pdw = pb[ofs] + ( pb[ofs + 1] << 8 ) + ( pb[ofs + 2] << 16UL ) + ( pb[ofs + 3] << 24UL ); +Cleanup: + return err; +} + + + +ERR getbfwbig(const U8* pb, size_t cb, size_t ofs, U16* pw) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + sizeof(U16) > cb, WMP_errBufferOverflow); + *pw = (U16)( pb[ofs + 1] + ( pb[ofs] << 8 ) ); +Cleanup: + return err; +} + + + +ERR getbfdwbig(const U8* pb, size_t cb, size_t ofs, U32* pdw) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + sizeof(U32) > cb, WMP_errBufferOverflow); + *pdw = pb[ofs + 3] + ( pb[ofs + 2] << 8 ) + ( pb[ofs + 1] << 16UL ) + ( pb[ofs] << 24UL ); +Cleanup: + return err; +} + + + +ERR getbfwe(const U8* pb, size_t cb, size_t ofs, U16* pw, U8 endian) +{ + if ( endian == WMP_INTEL_ENDIAN ) + return ( getbfw(pb, cb, ofs, pw) ); + else + return ( getbfwbig(pb, cb, ofs, pw) ); +} + + + +ERR getbfdwe(const U8* pb, size_t cb, size_t ofs, U32* pdw, U8 endian) +{ + if ( endian == WMP_INTEL_ENDIAN ) + return ( getbfdw(pb, cb, ofs, pdw) ); + else + return ( getbfdwbig(pb, cb, ofs, pdw) ); +} + + + +ERR setbfcpy(U8* pb, size_t cb, size_t ofs, const U8* pbset, size_t cbset) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + cbset > cb, WMP_errBufferOverflow); + memcpy(&pb[ofs], pbset, cbset); +Cleanup: + return err; +} + + + +ERR setbfw(U8* pb, size_t cb, size_t ofs, U16 dw) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + sizeof(U16) > cb, WMP_errBufferOverflow); + pb[ofs] = (U8)dw; + pb[ofs + 1] = (U8)( dw >> 8 ); +Cleanup: + return err; +} + + + +ERR setbfdw(U8* pb, size_t cb, size_t ofs, U32 dw) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + sizeof(U32) > cb, WMP_errBufferOverflow); + pb[ofs] = (U8)dw; + pb[ofs + 1] = (U8)( dw >> 8 ); + pb[ofs + 2] = (U8)( dw >> 16 ); + pb[ofs + 3] = (U8)( dw >> 24 ); +Cleanup: + return err; +} + + + +ERR setbfwbig(U8* pb, size_t cb, size_t ofs, U16 dw) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + sizeof(U16) > cb, WMP_errBufferOverflow); + pb[ofs + 1] = (U8)dw; + pb[ofs] = (U8)( dw >> 8 ); +Cleanup: + return err; +} + + + +ERR setbfdwbig(U8* pb, size_t cb, size_t ofs, U32 dw) +{ + ERR err = WMP_errSuccess; + FailIf(ofs + sizeof(U32) > cb, WMP_errBufferOverflow); + pb[ofs + 3] = (U8)dw; + pb[ofs + 2] = (U8)( dw >> 8 ); + pb[ofs + 1] = (U8)( dw >> 16 ); + pb[ofs] = (U8)( dw >> 24 ); +Cleanup: + return err; +} + + + +//================================================================ +// BufferCalcIFDSize (arbitrary endian) +// StreamCalcIFDSize (little endian) +// +// count up the number of bytes needed to store the IFD and all +// associated data including a subordinate interoperability IFD if any +//================================================================ + + + +ERR BufferCalcIFDSize(const U8* pbdata, size_t cbdata, U32 ofsifd, U8 endian, U32* pcbifd) +{ + ERR err = WMP_errSuccess; + U16 cDir; + U16 i; + U32 ofsdir; + U32 cbifd = 0; + U32 cbEXIFIFD = 0; + U32 cbGPSInfoIFD = 0; + U32 cbInteroperabilityIFD = 0; + + *pcbifd = 0; + Call(getbfwe(pbdata, cbdata, ofsifd, &cDir, endian)); + + cbifd = sizeof(U16) + cDir * SizeofIFDEntry + sizeof(U32); + ofsdir = ofsifd + sizeof(U16); + for ( i = 0; i < cDir; i++ ) + { + U16 tag; + U16 type; + U32 count; + U32 value; + U32 datasize; + + Call(getbfwe(pbdata, cbdata, ofsdir, &tag, endian)); + Call(getbfwe(pbdata, cbdata, ofsdir + sizeof(U16), &type, endian)); + Call(getbfdwe(pbdata, cbdata, ofsdir + 2 * sizeof(U16), &count, endian)); + Call(getbfdwe(pbdata, cbdata, ofsdir + 2 * sizeof(U16) + sizeof(U32), &value, endian)); + FailIf(type == 0 || type >= sizeof(IFDEntryTypeSizes) / sizeof(IFDEntryTypeSizes[0]), WMP_errFail); + if ( tag == WMP_tagEXIFMetadata ) + { + Call(BufferCalcIFDSize(pbdata, cbdata, value, endian, &cbEXIFIFD)); + } + else if ( tag == WMP_tagGPSInfoMetadata ) + { + Call(BufferCalcIFDSize(pbdata, cbdata, value, endian, &cbGPSInfoIFD)); + } + else if ( tag == WMP_tagInteroperabilityIFD ) + { + Call(BufferCalcIFDSize(pbdata, cbdata, value, endian, &cbInteroperabilityIFD)); + } + else + { + datasize = IFDEntryTypeSizes[type] * count; + if ( datasize > 4 ) + cbifd += datasize; + } + ofsdir += SizeofIFDEntry; + } + if ( cbEXIFIFD != 0 ) + cbifd += ( cbifd & 1 ) + cbEXIFIFD; + if ( cbGPSInfoIFD != 0 ) + cbifd += ( cbifd & 1 ) + cbGPSInfoIFD; + if ( cbInteroperabilityIFD != 0 ) + cbifd += ( cbifd & 1 ) + cbInteroperabilityIFD; + + *pcbifd = cbifd; + +Cleanup: + return err; +} + + +ERR StreamCalcIFDSize(struct WMPStream* pWS, U32 uIFDOfs, U32 *pcbifd) +{ + ERR err = WMP_errSuccess; + size_t offCurPos = 0; + Bool GetPosOK = FALSE; + U16 cDir; + U32 i; + U32 ofsdir; + U32 cbifd = 0; + U32 cbEXIFIFD = 0; + U32 cbGPSInfoIFD = 0; + U32 cbInteroperabilityIFD = 0; + + *pcbifd = 0; + Call(pWS->GetPos(pWS, &offCurPos)); + GetPosOK = TRUE; + + Call(GetUShort(pWS, uIFDOfs, &cDir)); + cbifd = sizeof(U16) + cDir * SizeofIFDEntry + sizeof(U32); + ofsdir = uIFDOfs + sizeof(U16); + for ( i = 0; i < cDir; i++ ) + { + U16 tag; + U16 type; + U32 count; + U32 value; + U32 datasize; + + Call(GetUShort(pWS, ofsdir, &tag)); + Call(GetUShort(pWS, ofsdir + sizeof(U16), &type)); + Call(GetULong(pWS, ofsdir + 2 * sizeof(U16), &count)); + Call(GetULong(pWS, ofsdir + 2 * sizeof(U16) + sizeof(U32), &value)); + FailIf(type == 0 || type >= sizeof(IFDEntryTypeSizes) / sizeof(IFDEntryTypeSizes[0]), WMP_errUnsupportedFormat); + if ( tag == WMP_tagEXIFMetadata ) + { + Call(StreamCalcIFDSize(pWS, value, &cbEXIFIFD)); + } + else if ( tag == WMP_tagGPSInfoMetadata ) + { + Call(StreamCalcIFDSize(pWS, value, &cbGPSInfoIFD)); + } + else if ( tag == WMP_tagInteroperabilityIFD ) + { + Call(StreamCalcIFDSize(pWS, value, &cbInteroperabilityIFD)); + } + else + { + datasize = IFDEntryTypeSizes[type] * count; + if ( datasize > 4 ) + cbifd += datasize; + } + ofsdir += SizeofIFDEntry; + } + if ( cbEXIFIFD != 0 ) + cbifd += ( cbifd & 1 ) + cbEXIFIFD; + if ( cbGPSInfoIFD != 0 ) + cbifd += ( cbifd & 1 ) + cbGPSInfoIFD; + if ( cbInteroperabilityIFD != 0 ) + cbifd += ( cbifd & 1 ) + cbInteroperabilityIFD; + *pcbifd = cbifd; + +Cleanup: + if ( GetPosOK ) + Call(pWS->SetPos(pWS, offCurPos)); + return ( err ); +} + + + +// src IFD copied to dst IFD with any nested IFD's +// src IFD is arbitrary endian, arbitrary data arrangement +// dst IFD is little endian, data arranged in tag order +// dst IFD tags are ordered the same as src IFD so src IFD tags must be in order +ERR BufferCopyIFD(const U8* pbsrc, U32 cbsrc, U32 ofssrc, U8 endian, U8* pbdst, U32 cbdst, U32* pofsdst) +{ + ERR err = WMP_errSuccess; + U16 cDir; + U16 i; + U16 ofsEXIFIFDEntry = 0; + U16 ofsGPSInfoIFDEntry = 0; + U16 ofsInteroperabilityIFDEntry = 0; + U32 ofsEXIFIFD = 0; + U32 ofsGPSInfoIFD = 0; + U32 ofsInteroperabilityIFD = 0; + U32 ofsdstnextdata; + U32 ofsdst = *pofsdst; + U32 ofssrcdir; + U32 ofsdstdir; + U32 ofsnextifd; + + Call(getbfwe(pbsrc, cbsrc, ofssrc, &cDir, endian)); + Call(setbfw(pbdst, cbdst, ofsdst, cDir)); + ofsnextifd = ofsdst + sizeof(U16) + SizeofIFDEntry * cDir; + ofsdstnextdata = ofsnextifd + sizeof(U32); + + ofssrcdir = ofssrc + sizeof(U16); + ofsdstdir = ofsdst + sizeof(U16); + for ( i = 0; i < cDir; i++ ) + { + U16 tag; + U16 type; + U32 count; + U32 value; + U32 size; + + Call(getbfwe(pbsrc, cbsrc, ofssrcdir, &tag, endian)); + Call(setbfw(pbdst, cbdst, ofsdstdir, tag)); + + Call(getbfwe(pbsrc, cbsrc, ofssrcdir + sizeof(U16), &type, endian)); + Call(setbfw(pbdst, cbdst, ofsdstdir + sizeof(U16), type)); + + Call(getbfdwe(pbsrc, cbsrc, ofssrcdir + 2 * sizeof(U16), &count, endian)); + Call(setbfdw(pbdst, cbdst, ofsdstdir + 2 * sizeof(U16), count)); + + Call(getbfdwe(pbsrc, cbsrc, ofssrcdir + 2 * sizeof(U16) + sizeof(U32), &value, endian)); + Call(setbfdw(pbdst, cbdst, ofsdstdir + 2 * sizeof(U16) + sizeof(U32), 0)); + + FailIf(type == 0 || type >= sizeof(IFDEntryTypeSizes) / sizeof(IFDEntryTypeSizes[0]), WMP_errFail); + if ( tag == WMP_tagEXIFMetadata ) + { + ofsEXIFIFDEntry = (U16) ofsdstdir; + ofsEXIFIFD = value; + } + else if ( tag == WMP_tagGPSInfoMetadata ) + { + ofsGPSInfoIFDEntry = (U16) ofsdstdir; + ofsGPSInfoIFD = value; + } + else if ( tag == WMP_tagInteroperabilityIFD ) + { + ofsInteroperabilityIFDEntry = (U16) ofsdstdir; + ofsInteroperabilityIFD = value; + } + else + { + U32 ofsdstdata = ofsdstdir + 2 * sizeof(U16) + sizeof(U32); + U32 ofssrcdata = ofssrcdir + 2 * sizeof(U16) + sizeof(U32); + size = count * IFDEntryTypeSizes[type]; + if ( size > 4 ) + { + ofssrcdata = value; + Call(setbfdw(pbdst, cbdst, ofsdstdata, ofsdstnextdata)); + ofsdstdata = ofsdstnextdata; + ofsdstnextdata += size; + } + FailIf(ofssrcdata + size > cbsrc || ofsdstdata + size > cbdst, WMP_errBufferOverflow); + if ( size == count || endian == WMP_INTEL_ENDIAN ) + // size == count means 8-bit data means endian doesn't matter + memcpy(&pbdst[ofsdstdata], &pbsrc[ofssrcdata], size); + else + { // big endian source and endian matters + U32 j; + + switch ( IFDEntryTypeSizes[type] ) + { + case 2: + for ( j = 0; j < count; j++ ) + { + U16 w; + getbfwbig(pbsrc, cbsrc, ofssrcdata + j * sizeof(U16), &w); + setbfw(pbdst, cbdst, ofsdstdata + j * sizeof(U16), w); + } + break; + case 8: + if ( type == WMP_typDOUBLE ) + { + for ( j = 0; j < count; j++ ) + { + U32 dwlo; + U32 dwhi; + getbfdwbig(pbsrc, cbsrc, ofssrcdata + j * 8, &dwhi); + getbfdwbig(pbsrc, cbsrc, ofssrcdata + j * 8 + sizeof(U32), &dwlo); + setbfdw(pbdst, cbdst, ofsdstdata + j * 8, dwlo); + setbfdw(pbdst, cbdst, ofsdstdata + j * 8 + sizeof(U32), dwhi); + } + break; + } + count *= 2; + // RATIONAL's fall through to be handled as LONG's + case 4: + for ( j = 0; j < count; j++ ) + { + U32 dw; + getbfdwbig(pbsrc, cbsrc, ofssrcdata + j * sizeof(U32), &dw); + setbfdw(pbdst, cbdst, ofsdstdata + j * sizeof(U32), dw); + } + break; + } + } + } + ofssrcdir += SizeofIFDEntry; + ofsdstdir += SizeofIFDEntry; + } + Call(setbfdw(pbdst, cbdst, ofsnextifd, 0)); // no nextIFD + + if ( ofsEXIFIFDEntry != 0 ) + { + ofsdstnextdata += ( ofsdstnextdata & 1 ); + Call(setbfdw(pbdst, cbdst, ofsEXIFIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata)); + Call(BufferCopyIFD(pbsrc, cbsrc, ofsEXIFIFD, endian, pbdst, cbdst, &ofsdstnextdata)); + } + if ( ofsGPSInfoIFDEntry != 0 ) + { + ofsdstnextdata += ( ofsdstnextdata & 1 ); + Call(setbfdw(pbdst, cbdst, ofsGPSInfoIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata)); + Call(BufferCopyIFD(pbsrc, cbsrc, ofsGPSInfoIFD, endian, pbdst, cbdst, &ofsdstnextdata)); + } + if ( ofsInteroperabilityIFDEntry != 0 ) + { + ofsdstnextdata += ( ofsdstnextdata & 1 ); + Call(setbfdw(pbdst, cbdst, ofsInteroperabilityIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata)); + Call(BufferCopyIFD(pbsrc, cbsrc, ofsInteroperabilityIFD, endian, pbdst, cbdst, &ofsdstnextdata)); + } + *pofsdst = ofsdstnextdata; + +Cleanup: + return err; +} + + + +// src IFD copied to dst IFD with any nested IFD's +// src IFD is little endian, arbitrary data arrangement +// dst IFD is little endian, data arranged in tag order +// dst IFD tags are ordered the same as src IFD so src IFD tags must be in order +ERR StreamCopyIFD(struct WMPStream* pWS, U32 ofssrc, U8* pbdst, U32 cbdst, U32* pofsdst) +{ + ERR err = WMP_errSuccess; + size_t offCurPos = 0; + Bool GetPosOK = FALSE; + U16 cDir; + U16 i; + U16 ofsEXIFIFDEntry = 0; + U16 ofsGPSInfoIFDEntry = 0; + U16 ofsInteroperabilityIFDEntry = 0; + U32 ofsEXIFIFD = 0; + U32 ofsGPSInfoIFD = 0; + U32 ofsInteroperabilityIFD = 0; + U32 ofsdstnextdata; + U32 ofsdst = *pofsdst; + U32 ofssrcdir; + U32 ofsdstdir; + U32 ofsnextifd; + + Call(pWS->GetPos(pWS, &offCurPos)); + GetPosOK = TRUE; + + Call(GetUShort(pWS, ofssrc, &cDir)); + Call(setbfw(pbdst, cbdst, ofsdst, cDir)); + + ofsnextifd = ofsdst + sizeof(U16) + SizeofIFDEntry * cDir; + ofsdstnextdata = ofsnextifd + sizeof(U32); + + ofssrcdir = ofssrc + sizeof(U16); + ofsdstdir = ofsdst + sizeof(U16); + for ( i = 0; i < cDir; i++ ) + { + U16 tag; + U16 type; + U32 count; + U32 value; + U32 size; + + Call(GetUShort(pWS, ofssrcdir, &tag)); + Call(setbfw(pbdst, cbdst, ofsdstdir, tag)); + + Call(GetUShort(pWS, ofssrcdir + sizeof(U16), &type)); + Call(setbfw(pbdst, cbdst, ofsdstdir + sizeof(U16), type)); + + Call(GetULong(pWS, ofssrcdir + 2 * sizeof(U16), &count)); + Call(setbfdw(pbdst, cbdst, ofsdstdir + 2 * sizeof(U16), count)); + + Call(GetULong(pWS, ofssrcdir + 2 * sizeof(U16) + sizeof(U32), &value)); + Call(setbfdw(pbdst, cbdst, ofsdstdir + 2 * sizeof(U16) + sizeof(U32), 0)); + + FailIf(type == 0 || type >= sizeof(IFDEntryTypeSizes) / sizeof(IFDEntryTypeSizes[0]), WMP_errFail); + if ( tag == WMP_tagEXIFMetadata ) + { + ofsEXIFIFDEntry = (U16) ofsdstdir; + ofsEXIFIFD = value; + } + else if ( tag == WMP_tagGPSInfoMetadata ) + { + ofsGPSInfoIFDEntry = (U16) ofsdstdir; + ofsGPSInfoIFD = value; + } + else if ( tag == WMP_tagInteroperabilityIFD ) + { + ofsInteroperabilityIFDEntry = (U16) ofsdstdir; + ofsInteroperabilityIFD = value; + } + else + { + U32 ofsdstdata = ofsdstdir + 2 * sizeof(U16) + sizeof(U32); + U32 ofssrcdata = ofssrcdir + 2 * sizeof(U16) + sizeof(U32); + size = count * IFDEntryTypeSizes[type]; + if ( size > 4 ) + { + ofssrcdata = value; + Call(setbfdw(pbdst, cbdst, ofsdstdata, ofsdstnextdata)); + ofsdstdata = ofsdstnextdata; + ofsdstnextdata += size; + } + FailIf(ofsdstdata + size > cbdst, WMP_errBufferOverflow); + Call(pWS->SetPos(pWS, ofssrcdata)); + Call(pWS->Read(pWS, &pbdst[ofsdstdata], size)); + } + ofssrcdir += SizeofIFDEntry; + ofsdstdir += SizeofIFDEntry; + } + Call(setbfdw(pbdst, cbdst, ofsnextifd, 0)); // no nextIFD + + if ( ofsEXIFIFDEntry != 0 ) + { + ofsdstnextdata += ( ofsdstnextdata & 1 ); + Call(setbfdw(pbdst, cbdst, ofsEXIFIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata)); + Call(StreamCopyIFD(pWS, ofsEXIFIFD, pbdst, cbdst, &ofsdstnextdata)); + } + if ( ofsGPSInfoIFDEntry != 0 ) + { + ofsdstnextdata += ( ofsdstnextdata & 1 ); + Call(setbfdw(pbdst, cbdst, ofsGPSInfoIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata)); + Call(StreamCopyIFD(pWS, ofsGPSInfoIFD, pbdst, cbdst, &ofsdstnextdata)); + } + if ( ofsInteroperabilityIFDEntry != 0 ) + { + ofsdstnextdata += ( ofsdstnextdata & 1 ); + Call(setbfdw(pbdst, cbdst, ofsInteroperabilityIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata)); + Call(StreamCopyIFD(pWS, ofsInteroperabilityIFD, pbdst, cbdst, &ofsdstnextdata)); + } + *pofsdst = ofsdstnextdata; + +Cleanup: + if ( GetPosOK ) + Call(pWS->SetPos(pWS, offCurPos)); + return err; +} + + + +//================================================================ +ERR GetUShort( + __in_ecount(1) struct WMPStream* pWS, + size_t offPos, + __out_ecount(1) U16* puValue) +{ + ERR err = WMP_errSuccess; + U8 cVal; + + Call(pWS->SetPos(pWS, offPos)); + Call(pWS->Read(pWS, &cVal, sizeof(cVal))); + puValue[0] = (U16) cVal; + Call(pWS->Read(pWS, &cVal, sizeof(cVal))); + puValue[0] += ((U16) cVal) << 8; + +Cleanup: + return err; +} + +ERR PutUShort( + __in_ecount(1) struct WMPStream* pWS, + size_t offPos, + U16 uValue) +{ + ERR err = WMP_errSuccess; + U8 cVal = (U8) uValue; + + Call(pWS->SetPos(pWS, offPos)); + Call(pWS->Write(pWS, &cVal, sizeof(cVal))); + cVal = (U8) (uValue >> 8); + Call(pWS->Write(pWS, &cVal, sizeof(cVal))); + +Cleanup: + return err; +} + +ERR GetULong( + __in_ecount(1) struct WMPStream* pWS, + size_t offPos, + __out_ecount(1) U32* puValue) +{ + ERR err = WMP_errSuccess; + U8 cVal; + + Call(pWS->SetPos(pWS, offPos)); + Call(pWS->Read(pWS, &cVal, sizeof(cVal))); + puValue[0] = (U32) cVal; + Call(pWS->Read(pWS, &cVal, sizeof(cVal))); + puValue[0] += ((U32) cVal) << 8; + Call(pWS->Read(pWS, &cVal, sizeof(cVal))); + puValue[0] += ((U32) cVal) << 16; + Call(pWS->Read(pWS, &cVal, sizeof(cVal))); + puValue[0] += ((U32) cVal) << 24; + +Cleanup: + return err; +} + +ERR PutULong( + __in_ecount(1) struct WMPStream* pWS, + size_t offPos, + U32 uValue) +{ + ERR err = WMP_errSuccess; + U8 cVal = (U8) uValue; + + Call(pWS->SetPos(pWS, offPos)); + Call(pWS->Write(pWS, &cVal, sizeof(cVal))); + cVal = (U8) (uValue >> 8); + Call(pWS->Write(pWS, &cVal, sizeof(cVal))); + cVal = (U8) (uValue >> 16); + Call(pWS->Write(pWS, &cVal, sizeof(cVal))); + cVal = (U8) (uValue >> 24); + Call(pWS->Write(pWS, &cVal, sizeof(cVal))); + +Cleanup: + return err; +} + + +ERR ReadBinaryData(__in_ecount(1) struct WMPStream* pWS, + const __in_win U32 uCount, + const __in_win U32 uValue, + U8 **ppbData) +{ + ERR err = WMP_errSuccess; + U8 *pbData = NULL; + + Call(PKAlloc((void **) &pbData, uCount + 2)); // Allocate buffer to store data with space for an added ascii or unicode null + if (uCount <= 4) + { + unsigned int i; + for (i = 0; i < uCount; i++) + pbData[i] = ((U8*)&uValue)[i]; // Copy least sig bytes - we assume 'II' type TIFF files + } + else + { + size_t offPosPrev; + + Call(pWS->GetPos(pWS, &offPosPrev)); + Call(pWS->SetPos(pWS, uValue)); + Call(pWS->Read(pWS, pbData, uCount)); + Call(pWS->SetPos(pWS, offPosPrev)); + } + + *ppbData = pbData; + +Cleanup: + if (Failed(err)) + { + if (pbData) + PKFree((void **) &pbData); + } + return err; +} + + +ERR ReadPropvar(__in_ecount(1) struct WMPStream* pWS, + const __in_win U16 uType, + const __in_win U32 uCount, + const __in_win U32 uValue, + __out_win DPKPROPVARIANT *pvar) +{ + ERR err = WMP_errSuccess; + // U8 *pbData = NULL; + + memset(pvar, 0, sizeof(*pvar)); + if (uCount == 0) + goto Cleanup; // Nothing to read in here + + switch (uType) + { + case WMP_typASCII: + pvar->vt = DPKVT_LPSTR; + Call(ReadBinaryData(pWS, uCount, uValue, (U8 **) &pvar->VT.pszVal)); + assert(0 == pvar->VT.pszVal[uCount - 1]); // Check that it's null-terminated + // make sure (ReadBinaryData allocated uCount + 2 so this and unicode can have forced nulls) + pvar->VT.pszVal[uCount] = 0; + break; + + case WMP_typBYTE: + case WMP_typUNDEFINED: + // Return as regular C array rather than safearray, as this type is sometimes + // used to convey unicode (which does not require a count field). Caller knows + // uCount and can convert to safearray if necessary. + pvar->vt = (DPKVT_BYREF | DPKVT_UI1); + Call(ReadBinaryData(pWS, uCount, uValue, &pvar->VT.pbVal)); + break; + + case WMP_typSHORT: + if (1 == uCount) + { + pvar->vt = DPKVT_UI2; + pvar->VT.uiVal = (U16)(uValue & 0x0000FFFF); + } + else if (2 == uCount) + { + pvar->vt = DPKVT_UI4; + pvar->VT.ulVal = uValue; + } + else + { + assert(FALSE); // NYI + FailIf(TRUE, WMP_errNotYetImplemented); + } + break; + + default: + assert(FALSE); // Unhandled type + FailIf(TRUE, WMP_errNotYetImplemented); + break; + } + +Cleanup: + return err; +} + + +ERR WriteWmpDE( + __in_ecount(1) struct WMPStream* pWS, + size_t *pOffPos, + const __in_ecount(1) WmpDE* pDE, + const U8 *pbData, + U32 *pcbDataWrittenToOffset) +{ + ERR err = WMP_errSuccess; + size_t offPos = *pOffPos; + + assert(-1 != pDE->uCount); + assert(-1 != pDE->uValueOrOffset); + + if (pcbDataWrittenToOffset) + { + assert(pbData); // Makes no sense to provide this arg without pbData + *pcbDataWrittenToOffset = 0; + } + + Call(PutUShort(pWS, offPos, pDE->uTag)); offPos += 2; + Call(PutUShort(pWS, offPos, pDE->uType)); offPos += 2; + Call(PutULong(pWS, offPos, pDE->uCount)); offPos += 4; + + switch (pDE->uType) + { + + case WMP_typASCII: + case WMP_typUNDEFINED: + case WMP_typBYTE: + if (pDE->uCount <= 4) + { + U8 pad[4] = {0}; + Call(pWS->SetPos(pWS, offPos)); + + if (NULL == pbData) + pbData = (U8*)&pDE->uValueOrOffset; + + Call(pWS->Write(pWS, pbData, pDE->uCount)); + Call(pWS->Write(pWS, pad, 4 - pDE->uCount)); offPos += 4; + } + else + { + Call(PutULong(pWS, offPos, pDE->uValueOrOffset)); offPos += 4; + + // Write the data if requested to do so + if (pbData) + { + Call(pWS->SetPos(pWS, pDE->uValueOrOffset)); + Call(pWS->Write(pWS, pbData, pDE->uCount)); + Call(pWS->SetPos(pWS, offPos)); + *pcbDataWrittenToOffset = pDE->uCount; + } + } + break; + + case WMP_typSHORT: + if (pDE->uCount <= 2) + { + U16 uiShrt1 = 0; + U16 uiShrt2 = 0; + + if (NULL == pbData) + pbData = (U8*)&pDE->uValueOrOffset; + + if (pDE->uCount > 0) + uiShrt1 = *((U16*)pbData); + + if (pDE->uCount > 1) + { + assert(FALSE); // Untested - remove this assert after this has been tested + uiShrt2 = *(U16*)(pbData + 2); + } + + Call(PutUShort(pWS, offPos, uiShrt1)); offPos += 2; + Call(PutUShort(pWS, offPos, uiShrt2)); offPos += 2; + } + else + { + assert(FALSE); // Untested - remove this assert after this has been tested + Call(PutULong(pWS, offPos, pDE->uValueOrOffset)); offPos += 4; + + // Write the data if requested to do so + if (pbData) + { + U32 i; + Call(pWS->SetPos(pWS, pDE->uValueOrOffset)); + for (i = 0; i < pDE->uCount; i++) + { + const U16 uiShort = *(U16*)(pbData + i*sizeof(U16)); + Call(PutUShort(pWS, offPos, uiShort)); // Write one at a time for endian purposes - but inefficient + } + Call(pWS->SetPos(pWS, offPos)); + *pcbDataWrittenToOffset = pDE->uCount * sizeof(U16); + } + + } + break; + + case WMP_typFLOAT: + case WMP_typLONG: + if (pDE->uCount <= 1) + { + if (NULL == pbData) + pbData = (U8*)&pDE->uValueOrOffset; + + Call(PutULong(pWS, offPos, *(U32*)pbData)); offPos += 4; + } + else + { + assert(FALSE); // Untested - remove this assert after this has been tested + Call(PutULong(pWS, offPos, pDE->uValueOrOffset)); offPos += 4; + + // Write the data if requested to do so + if (pbData) + { + U32 i; + Call(pWS->SetPos(pWS, pDE->uValueOrOffset)); + for (i = 0; i < pDE->uCount; i++) + { + const U32 uLong = *(U32*)(pbData + i*sizeof(U32)); + Call(PutULong(pWS, offPos, uLong)); // Write one at a time for endian purposes - but inefficient + } + Call(pWS->SetPos(pWS, offPos)); + *pcbDataWrittenToOffset = pDE->uCount * sizeof(U32); + } + } + break; + + default: + assert(FALSE); // Alert the programmer + Call(WMP_errInvalidParameter); + break; + } + +Cleanup: + *pOffPos = offPos; + return err; +} + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.h b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.h new file mode 100644 index 0000000..1a0b2a0 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.h @@ -0,0 +1,258 @@ +//*@@@+++@@@@****************************************************************** +// +// Copyright © Microsoft Corp. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*@@@---@@@@****************************************************************** +#pragma once + +#include +#ifndef _WIN32 +#include +#endif + +#ifndef UNREFERENCED_PARAMETER +#define UNREFERENCED_PARAMETER(P) { (P) = (P); } +#endif + +//================================================================ +// Container +//================================================================ + +// Keep these in sort order so that we can easily confirm we are outputting tags in ascending order +#define WMP_tagNull 0 + +#define WMP_tagDocumentName 0x010d // Descriptive metadata tag +#define WMP_tagImageDescription 0x010e // Descriptive metadata tag +#define WMP_tagCameraMake 0x010f // Descriptive metadata tag +#define WMP_tagCameraModel 0x0110 // Descriptive metadata tag +#define WMP_tagPageName 0x011d // Descriptive metadata tag +#define WMP_tagPageNumber 0x0129 // Descriptive metadata tag +#define WMP_tagSoftware 0x0131 // Descriptive metadata tag +#define WMP_tagDateTime 0x0132 // Descriptive metadata tag +#define WMP_tagArtist 0x013b // Descriptive metadata tag +#define WMP_tagHostComputer 0x013c // Descriptive metadata tag + +#define WMP_tagXMPMetadata 0x02bc + +#define WMP_tagRatingStars 0x4746 // Descriptive metadata tag +#define WMP_tagRatingValue 0x4749 // Descriptive metadata tag +#define WMP_tagCopyright 0x8298 // Descriptive metadata tag + +#define WMP_tagEXIFMetadata 0x8769 +#define WMP_tagGPSInfoMetadata 0x8825 +#define WMP_tagIPTCNAAMetadata 0x83bb +#define WMP_tagPhotoshopMetadata 0x8649 +#define WMP_tagInteroperabilityIFD 0xa005 +#define WMP_tagIccProfile 0x8773 // Need to use same tag as TIFF!! + +#define WMP_tagCaption 0x9c9b // Descriptive metadata tag + +#define WMP_tagPixelFormat 0xbc01 +#define WMP_tagTransformation 0xbc02 +#define WMP_tagCompression 0xbc03 +#define WMP_tagImageType 0xbc04 + +#define WMP_tagImageWidth 0xbc80 +#define WMP_tagImageHeight 0xbc81 + +#define WMP_tagWidthResolution 0xbc82 +#define WMP_tagHeightResolution 0xbc83 + +#define WMP_tagImageOffset 0xbcc0 +#define WMP_tagImageByteCount 0xbcc1 +#define WMP_tagAlphaOffset 0xbcc2 +#define WMP_tagAlphaByteCount 0xbcc3 +#define WMP_tagImageDataDiscard 0xbcc4 +#define WMP_tagAlphaDataDiscard 0xbcc5 + + +#define WMP_typBYTE 1 +#define WMP_typASCII 2 +#define WMP_typSHORT 3 +#define WMP_typLONG 4 +#define WMP_typRATIONAL 5 +#define WMP_typSBYTE 6 +#define WMP_typUNDEFINED 7 +#define WMP_typSSHORT 8 +#define WMP_typSLONG 9 +#define WMP_typSRATIONAL 10 +#define WMP_typFLOAT 11 +#define WMP_typDOUBLE 12 + + +#define WMP_valCompression 0xbc +#define WMP_valWMPhotoID WMP_valCompression + + +#ifdef _WIN32 +#define __in_win __in +#define __out_win __out +#endif + + +//================================================================ + +typedef enum +{ + DPKVT_EMPTY = 0, + DPKVT_UI1 = 17, + DPKVT_UI2 = 18, + DPKVT_UI4 = 19, + DPKVT_LPSTR = 30, + DPKVT_LPWSTR = 31, + DPKVT_BYREF = 0x4000, +} DPKVARTYPE; + +typedef struct DPKPROPVARIANT +{ + DPKVARTYPE vt; + union + { + U8 bVal; // DPKVT_UI1 + U16 uiVal; // DPKVT_UI2 + U32 ulVal; // DPKVT_UI4 + char *pszVal; // DPKVT_LPSTR + U16 *pwszVal; // DPKVT_LPWSTR + U8 *pbVal; // DPKVT_BYREF | DPKVT_UI1 + } VT; +} DPKPROPVARIANT; + +typedef struct DESCRIPTIVEMETADATA +{ + DPKPROPVARIANT pvarImageDescription; // WMP_tagImageDescription + DPKPROPVARIANT pvarCameraMake; // WMP_tagCameraMake + DPKPROPVARIANT pvarCameraModel; // WMP_tagCameraModel + DPKPROPVARIANT pvarSoftware; // WMP_tagSoftware + DPKPROPVARIANT pvarDateTime; // WMP_tagDateTime + DPKPROPVARIANT pvarArtist; // WMP_tagArtist + DPKPROPVARIANT pvarCopyright; // WMP_tagCopyright + DPKPROPVARIANT pvarRatingStars; // WMP_tagRatingStars + DPKPROPVARIANT pvarRatingValue; // WMP_tagRatingValue + DPKPROPVARIANT pvarCaption; // WMP_tagCaption + DPKPROPVARIANT pvarDocumentName; // WMP_tagDocumentName + DPKPROPVARIANT pvarPageName; // WMP_tagPageName + DPKPROPVARIANT pvarPageNumber; // WMP_tagPageNumber + DPKPROPVARIANT pvarHostComputer; // WMP_tagHostComputer +} DESCRIPTIVEMETADATA; + +typedef struct tagWmpDE +{ + U16 uTag; + U16 uType; + U32 uCount; + U32 uValueOrOffset; +} WmpDE; + +typedef struct tagWmpDEMisc +{ + U32 uImageOffset; + U32 uImageByteCount; + U32 uAlphaOffset; + U32 uAlphaByteCount; + + U32 uOffPixelFormat; + U32 uOffImageByteCount; + U32 uOffAlphaOffset; + U32 uOffAlphaByteCount; + U32 uColorProfileOffset; + U32 uColorProfileByteCount; + U32 uXMPMetadataOffset; + U32 uXMPMetadataByteCount; + U32 uEXIFMetadataOffset; + U32 uEXIFMetadataByteCount; + U32 uGPSInfoMetadataOffset; + U32 uGPSInfoMetadataByteCount; + U32 uIPTCNAAMetadataOffset; + U32 uIPTCNAAMetadataByteCount; + U32 uPhotoshopMetadataOffset; + U32 uPhotoshopMetadataByteCount; + U32 uDescMetadataOffset; + U32 uDescMetadataByteCount; +} WmpDEMisc; + + +//================================================================ +EXTERN_C ERR GetUShort( + __in_ecount(1) struct WMPStream* pWS, + size_t offPos, + __out_ecount(1) U16* puValue +); + +EXTERN_C ERR PutUShort( + __in_ecount(1) struct WMPStream* pWS, + size_t offPos, + U16 uValue +); + +EXTERN_C ERR GetULong( + __in_ecount(1) struct WMPStream* pWS, + size_t offPos, + __out_ecount(1) U32* puValue +); + +EXTERN_C ERR PutULong( + __in_ecount(1) struct WMPStream* pWS, + size_t offPos, + U32 uValue +); + +EXTERN_C ERR WriteWmpDE( + __in_ecount(1) struct WMPStream* pWS, + size_t *pOffPos, + const __in_ecount(1) WmpDE* pDE, + const U8 *pbData, + U32 *pcbDataWrittenToOffset +); + + +EXTERN_C ERR ReadPropvar(__in_ecount(1) struct WMPStream* pWS, + const __in_win U16 uType, + const __in_win U32 uCount, + const __in_win U32 uValue, + __out_win DPKPROPVARIANT *pvar); + + + +// read and write little endian words/dwords from a buffer on both big and little endian cpu's +// with full buffer overflow checking + +#define WMP_INTEL_ENDIAN ('I') + +EXTERN_C ERR getbfcpy(U8* pbdest, const U8* pb, size_t cb, size_t ofs, U32 n); +EXTERN_C ERR getbfw(const U8* pb, size_t cb, size_t ofs, U16* pw); +EXTERN_C ERR getbfdw(const U8* pb, size_t cb, size_t ofs, U32* pdw); +EXTERN_C ERR getbfwbig(const U8* pb, size_t cb, size_t ofs, U16* pw); +EXTERN_C ERR getbfdwbig(const U8* pb, size_t cb, size_t ofs, U32* pdw); +EXTERN_C ERR getbfwe(const U8* pb, size_t cb, size_t ofs, U16* pw, U8 endian); +EXTERN_C ERR getbfdwe(const U8* pb, size_t cb, size_t ofs, U32* pdw, U8 endian); +EXTERN_C ERR setbfcpy(U8* pb, size_t cb, size_t ofs, const U8* pbset, size_t cbset); +EXTERN_C ERR setbfw(U8* pb, size_t cb, size_t ofs, U16 dw); +EXTERN_C ERR setbfdw(U8* pb, size_t cb, size_t ofs, U32 dw); +EXTERN_C ERR setbfwbig(U8* pb, size_t cb, size_t ofs, U16 dw); +EXTERN_C ERR setbfdwbig(U8* pb, size_t cb, size_t ofs, U32 dw); +EXTERN_C ERR BufferCalcIFDSize(const U8* pb, size_t cb, U32 uIFDOfs, U8 endian, U32 *pcbifd); +EXTERN_C ERR StreamCalcIFDSize(struct WMPStream* pWS, U32 uIFDOfs, U32 *pcbifd); +EXTERN_C ERR BufferCopyIFD(const U8* pbsrc, U32 cbsrc, U32 ofssrc, U8 endian, U8* pbdest, U32 cbdest, U32* pofsdest); +EXTERN_C ERR StreamCopyIFD(struct WMPStream* pWS, U32 ofssrc, U8* pbdest, U32 cbdest, U32* pofsdest); diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.o b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.o new file mode 100644 index 0000000..11735f4 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/jxrlib/jxrgluelib/JXRMeta.o differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/license.json b/packages/jxr/dist/codec/node_modules/jpegxr/license.json new file mode 100644 index 0000000..2ce7f66 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/license.json @@ -0,0 +1 @@ +{"Name":"New BSD License (BSD)","Text":"Copyright (c) 2009, Microsoft\r\nAll rights reserved.\r\n\r\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\r\n\r\n* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\r\n\r\n* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\r\n\r\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.","Id":113424,"ShortName":"BSD","StartDate":"\/Date(1363627657140-0700)\/"} \ No newline at end of file diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/license.md b/packages/jxr/dist/codec/node_modules/jpegxr/license.md new file mode 100644 index 0000000..ac6d893 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/license.md @@ -0,0 +1,12 @@ +New BSD License (BSD) + +Copyright (c) 2009, Microsoft +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/package.json b/packages/jxr/dist/codec/node_modules/jpegxr/package.json new file mode 100644 index 0000000..e007188 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/package.json @@ -0,0 +1,31 @@ +{ + "name": "jpegxr", + "version": "0.3.0", + "description": "Wrapper for Microsoft's C JPEG XR image codec library", + "main": "wasm/jpegxr.js", + "files": [ + "license.md", + "readme.md", + "wasm/jpegxr.js" + ], + "scripts": { + "build": "make", + "test": "make test", + "prepare": "npm run-script build", + "prepublishOnly": "npm test" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/brion/jpegxr.git" + }, + "keywords": [ + "jpegxr", + "jxr" + ], + "author": "Brooke Vibber ", + "license": "BSD-3-Clause", + "bugs": { + "url": "https://github.com/brion/jpegxr/issues" + }, + "homepage": "https://github.com/brion/jpegxr#readme" +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/readme.md b/packages/jxr/dist/codec/node_modules/jpegxr/readme.md new file mode 100644 index 0000000..a826380 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/readme.md @@ -0,0 +1,135 @@ +# jpegxr - Rust and JavaScript wrapper library for decoding JPEG XR images + +This provides Rust and JavaScript wrappers around the C libjpegxr / jxrlib codec open-sourced by Microsoft. The code is included in-tree as it's no longer actively maintained, and the Codeplex source downloads may not last. + +Currently only decoding is supported, but adding an encoder interface should be straightforward. + +# Authors + +The wrapped C JPEG XR library was written by many fine folks at Microsoft! +Rust and JS code wrapping it, and tweaks to the C code, are by Brooke Vibber ``. + +# License + +BSD-style license; see `license.md` or the headers in source files. + +# Usage (Rust) + +```rust +use fs; +use jpegxr::{ImageDecode, PixelInfo}; + +// ... + +let input = File::open(filename)?; +let mut decoder = ImageDecode::with_reader(input)?; + +let (width, height) = decoder.get_size()?; +let info = PixelInfo::from_format(get_pixel_format()?); +let stride = width * info.bytes_per_pixel() / 8; +let size = stride * height; + +let buffer = Vec::::with_capacity(size); +buffer.resize(size, 0); +decoder.copy_all(&mut buffer, stride)?; + +// now do stuff with the data +``` + +# Usage (JS) + +Quick start: + +```js +let fs = require('fs'); +let jpegxr = require('jpegxr'); + +let bytes = fs.readFileSync(filename); +jpegxr().then((codec) => { + let image = codec.decode(bytes); + let stride = image.width * image.pixelInfo.bitsPerPixel / 8; + // do stuff with image.bytes +}); +``` + +The `jpegxr` module exports a factory function which asynchronously prepares the WebAssembly modules and returns an API wrapper object via a `Promise`. + +Call its `decode` method with a `Uint8Array` of input bytes to get back an object with the following structure: + +```js +{ + width: number, + height: number, + pixelInfo: { + channels: number, // 3, 4 etc + colorFormat: string, // "RGB" etc + bitDepth: string, // "8", "32Float" etc + bitsPerPixel: number, // 24, 32, 128 etc + hasAlpha: boolean, + premultipliedAlpha: boolean, + bgr: boolean, // indicates RGB has blue channel first, not red + }, + bytes: Uint8Array +} +``` + +Exceptions may be thrown in case of invalid data. The `bytes` array is standalone and backed by its own buffer, and does not need to be manually freed -- however this all incurs the cost of a single copy of both input and output data in/out of the WebAssembly module. + + +# Features + +Currently sports the ability to read basic image format (width/height/pixel format) from a JPEG XR image and decode its data to memory. Plan to add encoding, all the pieces are there, just haven't set it up yet. + +In Rust API you can ask for a subset of the image, which should allow progressive display during decoding, or to save time decoding unused macroblocks on a cropped view. + +HDR images with 32-bit floating point RGBA elements, as saved from the NVIDIA game screen capture tool, appear to decode correctly. + + +# Future plans + +* add encoder interface +* more testing of obscure stuff + + +# Building (JS) + +Building the JS via emscripten should work on macOS and Linux. On Windows I recommend using WSL to set up a Linux environment. + +Install the [emscripten SDK](https://emscripten.org/) and set it up in `PATH`. Either run `make` directly, or `npm run-script build` which runs `make` itself. + +Run `npm test` to run a verification script which loads a sample floating point HDR screenshot and calculates average red, green, and blue intensities to prove it loaded correctly. Results should look something like this, with no exceptions thrown: + +``` +% make test +node wasm/test.js +{ decode: [Function: decode] } +{ + width: 3440, + height: 1440, + pixelInfo: { + channels: 4, + colorFormat: 'RGB', + bitDepth: '32Float', + bitsPerPixel: 128, + hasAlpha: true, + premultipledAlpha: false, + bgr: false + }, + bytes: Uint8Array(79257600) [ + 0, 0, 136, 58, 0, 0, 250, 58, 0, 0, 63, 59, + 0, 0, 0, 0, 0, 0, 136, 58, 0, 0, 250, 58, + 0, 0, 63, 59, 0, 0, 0, 0, 0, 0, 136, 58, + 0, 0, 248, 58, 0, 0, 63, 59, 0, 0, 0, 0, + 0, 0, 136, 58, 0, 0, 246, 58, 0, 0, 62, 59, + 0, 0, 0, 0, 0, 0, 136, 58, 0, 0, 250, 58, + 0, 0, 63, 59, 0, 0, 0, 0, 0, 0, 136, 58, + 0, 0, 250, 58, 0, 0, 63, 59, 0, 0, 0, 0, + 0, 0, 136, 58, + ... 79257500 more items + ] +} +average red brightness: 1.4860534716607372 +average green brightness: 2.4572176722254246 +average blue brightness: 3.867482314063597 +``` + diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/samples/panel-hdr.jxr b/packages/jxr/dist/codec/node_modules/jpegxr/samples/panel-hdr.jxr new file mode 100644 index 0000000..8b8fc35 Binary files /dev/null and b/packages/jxr/dist/codec/node_modules/jpegxr/samples/panel-hdr.jxr differ diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/src/jpegxr_sys.rs b/packages/jxr/dist/codec/node_modules/jpegxr/src/jpegxr_sys.rs new file mode 100644 index 0000000..f327749 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/src/jpegxr_sys.rs @@ -0,0 +1,7 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/src/lib.rs b/packages/jxr/dist/codec/node_modules/jpegxr/src/lib.rs new file mode 100644 index 0000000..97a8991 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/src/lib.rs @@ -0,0 +1,857 @@ +// +// Copyright © Brooke Vibber +// Some rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// • Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// • Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// turn on all clippy's lints by default +#![warn(clippy::all)] +#![allow(unused_imports)] + +// this quiets the compiler about the C constant names +#![allow(non_upper_case_globals)] + +// this is triggered by test cases in bindgen code +// where it double-checks the offsets of struct members +#![allow(deref_nullptr)] + + +use std::convert::TryFrom; +use std::io::{self, Read, Seek, SeekFrom}; +use std::ffi::{NulError, c_void}; + +// Pull in the C library via bindgen +mod jpegxr_sys; +use jpegxr_sys::*; + +// For wrapping errors conveniently +use thiserror::Error; + +/// +/// Result wrapper for the library. +/// +pub type Result = std::result::Result; + +/// +/// Error type for the library; consolidates internal errors +/// and incoming errors from I/O and data marshalling. +/// +#[derive(Error, Debug)] +pub enum JXRError { + // Rust-side library errors + #[error("I/O error: {0}")] + IoError(#[from] io::Error), + #[error("null byte in string: {0}")] + NulError(#[from] NulError), + #[error("numeric conversion error: {0}")] + TryFromIntError(#[from] std::num::TryFromIntError), + + // Rust-side local errors + #[error("invalid data")] + InvalidData, + #[error("unrecognized pixel format GUID")] + UnrecognizedPixelFormat, + #[error("unrecognized color format")] + UnrecognizedColorFormat, + #[error("unrecognized photometric interpretation")] + UnrecognizedInterpretation, + #[error("unrecognized bit depth")] + UnrecognizedBitDepth, + + // C-side errors + #[error("unknown error")] + UnknownError, + #[error("fail")] + Fail, + #[error("not yet implemented")] + NotYetImplemented, + #[error("abstract method")] + AbstractMethod, + #[error("out of memory")] + OutOfMemory, + #[error("file I/O")] + FileIO, + #[error("buffer overflow")] + BufferOverflow, + #[error("invalid parameter")] + InvalidParameter, + #[error("invalid argument")] + InvalidArgument, + #[error("unsupported format")] + UnsupportedFormat, + #[error("incorrect codec version")] + IncorrectCodecVersion, + #[error("index not found")] + IndexNotFound, + #[error("out of sequence")] + OutOfSequence, + #[error("not initialized")] + NotInitialized, + #[error("must be multiple of 16 lines until last call")] + MustBeMultipleOf16LinesUntilLastCall, + #[error("planar alpha banded enc requires temp file")] + PlanarAlphaBandedEncRequiresTempFile, + #[error("alpha mode cannot be transcoded")] + AlphaModeCannotBeTranscoded, + #[error("incorrect codec sub-version")] + IncorrectCodecSubVersion +} +use JXRError::*; + +/// +/// Internal helper: wrap C calls with a ?-friendly Result. +/// +fn call(err: ERR) -> Result<()> { + if err >= 0 { + Ok(()) + } else { + Err(match err { + WMP_errFail => Fail, + WMP_errNotYetImplemented => NotYetImplemented, + WMP_errAbstractMethod => AbstractMethod, + WMP_errOutOfMemory => OutOfMemory, + WMP_errFileIO => FileIO, + WMP_errBufferOverflow => BufferOverflow, + WMP_errInvalidParameter => InvalidParameter, + WMP_errInvalidArgument => InvalidArgument, + WMP_errUnsupportedFormat => UnsupportedFormat, + WMP_errIncorrectCodecVersion => IncorrectCodecVersion, + WMP_errIndexNotFound => IndexNotFound, + WMP_errOutOfSequence => OutOfSequence, + WMP_errNotInitialized => NotInitialized, + WMP_errMustBeMultipleOf16LinesUntilLastCall => MustBeMultipleOf16LinesUntilLastCall, + WMP_errPlanarAlphaBandedEncRequiresTempFile => PlanarAlphaBandedEncRequiresTempFile, + WMP_errAlphaModeCannotBeTranscoded => AlphaModeCannotBeTranscoded, + WMP_errIncorrectCodecSubVersion => IncorrectCodecSubVersion, + _ => UnknownError + }) + } +} + +/// +/// Pixel format enum so you don't have to deal with GUIDs yourself. +/// Naming of these may change before 1.0, be warned. +/// +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum PixelFormat { + PixelFormatDontCare, + + // Indexed + PixelFormatBlackWhite, + PixelFormat8bppGray, + + // sRGB - Rec.709 color primaries, sRGB gamma, SDR only + PixelFormat16bppRGB555, + PixelFormat16bppRGB565, + PixelFormat16bppGray, + PixelFormat24bppBGR, + PixelFormat24bppRGB, + PixelFormat32bppBGR, + PixelFormat32bppBGRA, + PixelFormat32bppPBGRA, + PixelFormat32bppGrayFloat, + PixelFormat32bppRGB, + PixelFormat32bppRGBA, + PixelFormat32bppPRGBA, + PixelFormat48bppRGBFixedPoint, + + // scRGB - Rect.709 color primaries, linear, HDR-capable + PixelFormat16bppGrayFixedPoint, + PixelFormat32bppRGB101010, + PixelFormat48bppRGB, + PixelFormat64bppRGBA, + PixelFormat64bppPRGBA, + PixelFormat96bppRGBFixedPoint, + PixelFormat96bppRGBFloat, + PixelFormat128bppRGBAFloat, // This is used in NVIDIA HDR screenshots + PixelFormat128bppPRGBAFloat, + PixelFormat128bppRGBFloat, + + // various... + PixelFormat32bpp, + PixelFormat64bppRGBAFixedPoint, + PixelFormat64bppRGBFixedPoint, + PixelFormat128bppRGBAFixedPoint, + PixelFormat128bppRGBFixedPoint, + PixelFormat64bppRGBAHalf, + PixelFormat64bppRGBHalf, + PixelFormat48bppRGBHalf, + PixelFormat32bppRGBE, + PixelFormat16bppGrayHalf, + PixelFormat32bppGrayFixedPoint, + + PixelFormat64bppCMYK, + + PixelFormat24bpp3Channels, + PixelFormat32bpp4Channels, + PixelFormat40bpp5Channels, + PixelFormat48bpp6Channels, + PixelFormat56bpp7Channels, + PixelFormat64bpp8Channels, + + PixelFormat48bpp3Channels, + PixelFormat64bpp4Channels, + PixelFormat80bpp5Channels, + PixelFormat96bpp6Channels, + PixelFormat112bpp7Channels, + PixelFormat128bpp8Channels, + + PixelFormat40bppCMYKAlpha, + PixelFormat80bppCMYKAlpha, + + PixelFormat32bpp3ChannelsAlpha, + PixelFormat40bpp4ChannelsAlpha, + PixelFormat48bpp5ChannelsAlpha, + PixelFormat56bpp6ChannelsAlpha, + PixelFormat64bpp7ChannelsAlpha, + PixelFormat72bpp8ChannelsAlpha, + + PixelFormat64bpp3ChannelsAlpha, + PixelFormat80bpp4ChannelsAlpha, + PixelFormat96bpp5ChannelsAlpha, + PixelFormat112bpp6ChannelsAlpha, + PixelFormat128bpp7ChannelsAlpha, + PixelFormat144bpp8ChannelsAlpha, + + // YCrCb from Advanced Profile + PixelFormat12bppYCC420, + PixelFormat16bppYCC422, + PixelFormat20bppYCC422, + PixelFormat32bppYCC422, + PixelFormat24bppYCC444, + PixelFormat30bppYCC444, + PixelFormat48bppYCC444, + PixelFormat16bpp48bppYCC444FixedPoint, + PixelFormat20bppYCC420Alpha, + PixelFormat24bppYCC422Alpha, + PixelFormat30bppYCC422Alpha, + PixelFormat48bppYCC422Alpha, + PixelFormat32bppYCC444Alpha, + PixelFormat40bppYCC444Alpha, + PixelFormat64bppYCC444Alpha, + PixelFormat64bppYCC444AlphaFixedPoint, + + // CMYKDIRECT from Advanced Profile + PixelFormat32bppCMYKDIRECT, + PixelFormat64bppCMYKDIRECT, + PixelFormat40bppCMYKDIRECTAlpha, + PixelFormat80bppCMYKDIRECTAlpha, +} +use PixelFormat::*; + +static GUID_MAP: &[(&GUID, PixelFormat)] = unsafe { + &[ + (&GUID_PKPixelFormatDontCare, PixelFormatDontCare), + (&GUID_PKPixelFormatBlackWhite, PixelFormatBlackWhite), + (&GUID_PKPixelFormat8bppGray, PixelFormat8bppGray), + + // sRGB formats + (&GUID_PKPixelFormat16bppRGB555, PixelFormat16bppRGB555), + (&GUID_PKPixelFormat16bppRGB565, PixelFormat16bppRGB565), + (&GUID_PKPixelFormat16bppGray, PixelFormat16bppGray), + (&GUID_PKPixelFormat24bppBGR, PixelFormat24bppBGR), + (&GUID_PKPixelFormat24bppRGB, PixelFormat24bppRGB), + (&GUID_PKPixelFormat32bppBGR, PixelFormat32bppBGR), + (&GUID_PKPixelFormat32bppBGRA, PixelFormat32bppBGRA), + (&GUID_PKPixelFormat32bppPBGRA, PixelFormat32bppPBGRA), + (&GUID_PKPixelFormat32bppGrayFloat, PixelFormat32bppGrayFloat), + (&GUID_PKPixelFormat32bppRGB, PixelFormat32bppRGB), + (&GUID_PKPixelFormat32bppRGBA, PixelFormat32bppRGBA), + (&GUID_PKPixelFormat32bppPRGBA, PixelFormat32bppPRGBA), + (&GUID_PKPixelFormat48bppRGBFixedPoint, PixelFormat48bppRGBFixedPoint), + + // scRGB formats + (&GUID_PKPixelFormat16bppGrayFixedPoint, PixelFormat16bppGrayFixedPoint), + (&GUID_PKPixelFormat32bppRGB101010, PixelFormat32bppRGB101010), + (&GUID_PKPixelFormat48bppRGB, PixelFormat48bppRGB), + (&GUID_PKPixelFormat64bppRGBA, PixelFormat64bppRGBA), + (&GUID_PKPixelFormat64bppPRGBA, PixelFormat64bppPRGBA), + (&GUID_PKPixelFormat96bppRGBFixedPoint, PixelFormat96bppRGBFixedPoint), + (&GUID_PKPixelFormat96bppRGBFloat, PixelFormat96bppRGBFloat), + (&GUID_PKPixelFormat128bppRGBAFloat, PixelFormat128bppRGBAFloat), + (&GUID_PKPixelFormat128bppPRGBAFloat, PixelFormat128bppPRGBAFloat), + (&GUID_PKPixelFormat128bppRGBFloat, PixelFormat128bppRGBFloat), + + // CMYK formats + (&GUID_PKPixelFormat32bppCMYK, PixelFormat32bpp), + + // Photon formats + (&GUID_PKPixelFormat64bppRGBAFixedPoint, PixelFormat64bppRGBAFixedPoint), + (&GUID_PKPixelFormat64bppRGBFixedPoint, PixelFormat64bppRGBFixedPoint), + (&GUID_PKPixelFormat128bppRGBAFixedPoint, PixelFormat128bppRGBAFixedPoint), + (&GUID_PKPixelFormat128bppRGBFixedPoint, PixelFormat128bppRGBFixedPoint), + (&GUID_PKPixelFormat64bppRGBAHalf, PixelFormat64bppRGBAHalf), + (&GUID_PKPixelFormat64bppRGBHalf, PixelFormat64bppRGBHalf), + (&GUID_PKPixelFormat48bppRGB, PixelFormat48bppRGBHalf), + (&GUID_PKPixelFormat32bppRGBE, PixelFormat32bppRGBE), + (&GUID_PKPixelFormat16bppGrayHalf, PixelFormat16bppGrayHalf), + (&GUID_PKPixelFormat32bppGrayFixedPoint, PixelFormat32bppGrayFixedPoint), + + (&GUID_PKPixelFormat64bppCMYK, PixelFormat64bppCMYK), + + (&GUID_PKPixelFormat24bpp3Channels, PixelFormat24bpp3Channels), + (&GUID_PKPixelFormat32bpp4Channels, PixelFormat32bpp4Channels), + (&GUID_PKPixelFormat40bpp5Channels, PixelFormat40bpp5Channels), + (&GUID_PKPixelFormat48bpp6Channels, PixelFormat48bpp6Channels), + (&GUID_PKPixelFormat56bpp7Channels, PixelFormat56bpp7Channels), + (&GUID_PKPixelFormat64bpp8Channels, PixelFormat64bpp8Channels), + + (&GUID_PKPixelFormat48bpp3Channels, PixelFormat48bpp3Channels), + (&GUID_PKPixelFormat64bpp4Channels, PixelFormat64bpp4Channels), + (&GUID_PKPixelFormat80bpp5Channels, PixelFormat80bpp5Channels), + (&GUID_PKPixelFormat96bpp6Channels, PixelFormat96bpp6Channels), + (&GUID_PKPixelFormat112bpp7Channels, PixelFormat112bpp7Channels), + (&GUID_PKPixelFormat128bpp8Channels, PixelFormat128bpp8Channels), + + (&GUID_PKPixelFormat40bppCMYKAlpha, PixelFormat40bppCMYKAlpha), + (&GUID_PKPixelFormat80bppCMYKAlpha, PixelFormat80bppCMYKAlpha), + + (&GUID_PKPixelFormat32bpp3ChannelsAlpha, PixelFormat32bpp3ChannelsAlpha), + (&GUID_PKPixelFormat40bpp4ChannelsAlpha, PixelFormat40bpp4ChannelsAlpha), + (&GUID_PKPixelFormat48bpp5ChannelsAlpha, PixelFormat48bpp5ChannelsAlpha), + (&GUID_PKPixelFormat56bpp6ChannelsAlpha, PixelFormat56bpp6ChannelsAlpha), + (&GUID_PKPixelFormat64bpp7ChannelsAlpha, PixelFormat64bpp7ChannelsAlpha), + (&GUID_PKPixelFormat72bpp8ChannelsAlpha, PixelFormat72bpp8ChannelsAlpha), + + (&GUID_PKPixelFormat64bpp3ChannelsAlpha, PixelFormat64bpp3ChannelsAlpha), + (&GUID_PKPixelFormat80bpp4ChannelsAlpha, PixelFormat80bpp4ChannelsAlpha), + (&GUID_PKPixelFormat96bpp5ChannelsAlpha, PixelFormat96bpp5ChannelsAlpha), + (&GUID_PKPixelFormat112bpp6ChannelsAlpha, PixelFormat112bpp6ChannelsAlpha), + (&GUID_PKPixelFormat128bpp7ChannelsAlpha, PixelFormat128bpp7ChannelsAlpha), + (&GUID_PKPixelFormat144bpp8ChannelsAlpha, PixelFormat144bpp8ChannelsAlpha), + + /* YCrCb from Advanced Profile */ + (&GUID_PKPixelFormat12bppYCC420, PixelFormat12bppYCC420), + (&GUID_PKPixelFormat16bppYCC422, PixelFormat16bppYCC422), + (&GUID_PKPixelFormat20bppYCC422, PixelFormat20bppYCC422), + (&GUID_PKPixelFormat32bppYCC422, PixelFormat32bppYCC422), + (&GUID_PKPixelFormat24bppYCC444, PixelFormat24bppYCC444), + (&GUID_PKPixelFormat30bppYCC444, PixelFormat30bppYCC444), + (&GUID_PKPixelFormat48bppYCC444, PixelFormat48bppYCC444), + (&GUID_PKPixelFormat16bpp48bppYCC444FixedPoint, PixelFormat16bpp48bppYCC444FixedPoint), + (&GUID_PKPixelFormat20bppYCC420Alpha, PixelFormat20bppYCC420Alpha), + (&GUID_PKPixelFormat24bppYCC422Alpha, PixelFormat24bppYCC422Alpha), + (&GUID_PKPixelFormat30bppYCC422Alpha, PixelFormat30bppYCC422Alpha), + (&GUID_PKPixelFormat48bppYCC422Alpha, PixelFormat48bppYCC422Alpha), + (&GUID_PKPixelFormat32bppYCC444Alpha, PixelFormat32bppYCC444Alpha), + (&GUID_PKPixelFormat40bppYCC444Alpha, PixelFormat40bppYCC444Alpha), + (&GUID_PKPixelFormat64bppYCC444Alpha, PixelFormat64bppYCC444Alpha), + (&GUID_PKPixelFormat64bppYCC444AlphaFixedPoint, PixelFormat64bppYCC444AlphaFixedPoint), + + /* CMYKDIRECT from Advanced Profile */ + (&GUID_PKPixelFormat32bppCMYKDIRECT, PixelFormat32bppCMYKDIRECT), + (&GUID_PKPixelFormat64bppCMYKDIRECT, PixelFormat64bppCMYKDIRECT), + (&GUID_PKPixelFormat40bppCMYKDIRECTAlpha, PixelFormat40bppCMYKDIRECTAlpha), + (&GUID_PKPixelFormat80bppCMYKDIRECTAlpha, PixelFormat80bppCMYKDIRECTAlpha), + ] +}; + +impl PixelFormat { + + fn guid(&self) -> &'static GUID { + for (map_guid, map_val) in GUID_MAP { + if self == map_val { + return map_guid; + } + } + unreachable!("bad pixel format enum") + } + + fn from_guid(&guid: &GUID) -> Result { + for (&map_guid, map_val) in GUID_MAP { + if guid == map_guid { + return Ok(*map_val); + } + } + Err(UnrecognizedPixelFormat) + } + +} + +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum ColorFormat { + YOnly, + YUV420, + YUV422, + YUV444, + CMYK, + NComponent, + RGB, + RGBE +} + +impl ColorFormat { + fn from_raw(raw: COLORFORMAT) -> Result { + match raw { + COLORFORMAT_Y_ONLY => Ok(ColorFormat::YOnly), + COLORFORMAT_YUV_420 => Ok(ColorFormat::YUV420), + COLORFORMAT_YUV_422 => Ok(ColorFormat::YUV422), + COLORFORMAT_YUV_444 => Ok(ColorFormat::YUV444), + COLORFORMAT_CMYK => Ok(ColorFormat::CMYK), + COLORFORMAT_NCOMPONENT => Ok(ColorFormat::NComponent), + COLORFORMAT_CF_RGB => Ok(ColorFormat::RGB), + COLORFORMAT_CF_RGBE => Ok(ColorFormat::RGBE), + _ => Err(UnrecognizedColorFormat) + } + } +} + +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum PhotometricInterpretation { + WhiteIsZero, + BlackIsZero, + RGB, + RGBPalette, + TransparencyMask, + CMYK, + YCbCr, + CIELab, + NCH, + RGBE, // shared-exponent +} + +impl PhotometricInterpretation { + fn from_raw(raw: u32) -> Result { + use PhotometricInterpretation::*; + match raw { + PK_PI_W0 => Ok(WhiteIsZero), + PK_PI_B0 => Ok(BlackIsZero), + PK_PI_RGB => Ok(RGB), + PK_PI_RGBPalette => Ok(RGBPalette), + PK_PI_TransparencyMask => Ok(TransparencyMask), + PK_PI_CMYK => Ok(CMYK), + PK_PI_YCbCr => Ok(YCbCr), + PK_PI_CIELab => Ok(CIELab), + PK_PI_NCH => Ok(NCH), + PK_PI_RGBE => Ok(RGBE), + _ => Err(UnrecognizedInterpretation) + } + } +} + +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum BitDepthBits { + // regular ones + One, //White is foreground + Eight, + Sixteen, + SixteenS, + SixteenF, + ThirtyTwo, + ThirtyTwoS, + ThirtyTwoF, + + // irregular ones + Five, + Ten, + FiveSixFive, + + OneAlt, //Black is foreground +} + +impl BitDepthBits { + fn from_raw(raw: BITDEPTH_BITS) -> Result { + use BitDepthBits::*; + match raw { + BITDEPTH_BITS_BD_1 => Ok(One), + BITDEPTH_BITS_BD_8 => Ok(Eight), + BITDEPTH_BITS_BD_16 => Ok(Sixteen), + BITDEPTH_BITS_BD_16S => Ok(SixteenS), + BITDEPTH_BITS_BD_16F => Ok(SixteenF), + BITDEPTH_BITS_BD_32 => Ok(ThirtyTwo), + BITDEPTH_BITS_BD_32S => Ok(ThirtyTwoS), + BITDEPTH_BITS_BD_32F => Ok(ThirtyTwoF), + BITDEPTH_BITS_BD_5 => Ok(Five), + BITDEPTH_BITS_BD_10 => Ok(Ten), + BITDEPTH_BITS_BD_565 => Ok(FiveSixFive), + BITDEPTH_BITS_BD_1alt => Ok(OneAlt), + _ => Err(UnrecognizedBitDepth) + } + } +} + +pub struct PixelInfo { + raw: PKPixelInfo +} + +impl PixelInfo { + + fn from_guid(guid: &GUID) -> Result { + unsafe { + // It looks wrong to put a pointer into + // the struct, but it's fine because the + // entire struct gets overwritten, so the + // output struct contains a static-lifetime + // pointer. + let mut info = PixelInfo { + raw: std::mem::zeroed() + }; + info.raw.pGUIDPixFmt = guid; + call(PixelFormatLookup(&mut info.raw, LOOKUP_FORWARD as u8))?; + Ok(info) + } + } + + fn guid(&self) -> &GUID { + unsafe { + &*self.raw.pGUIDPixFmt + } + } + + pub fn from_format(format: PixelFormat) -> Self { + Self::from_guid(format.guid()).unwrap() + } + + pub fn format(&self) -> PixelFormat { + PixelFormat::from_guid(self.guid()).unwrap() + } + + pub fn channels(&self) -> usize { + self.raw.cChannel + } + + pub fn color_format(&self) -> ColorFormat { + ColorFormat::from_raw(self.raw.cfColorFormat).unwrap() + } + + pub fn bit_depth(&self) -> BitDepthBits { + BitDepthBits::from_raw(self.raw.bdBitDepth).unwrap() + } + + pub fn bits_per_pixel(&self) -> usize { + self.raw.cbitUnit as usize + } + + pub fn has_alpha(&self) -> bool { + (self.raw.grBit as u32 & PK_pixfmtHasAlpha) != 0 + } + + pub fn premultiplied_alpha(&self) -> bool { + (self.raw.grBit as u32 & PK_pixfmtPreMul) != 0 + } + + pub fn bgr(&self) -> bool { + (self.raw.grBit as u32 & PK_pixfmtBGR) != 0 + } + + pub fn photometric_interpretation(&self) -> PhotometricInterpretation { + PhotometricInterpretation::from_raw(self.raw.uInterpretation).unwrap() + } + + pub fn samples_per_pixel(&self) -> usize { + self.raw.uSamplePerPixel as usize + } +} + + +/// +/// Internal wrapper around a Read + Seek input file +/// into a read-only WMPStream the C library can grok. +/// +struct InputStream { + raw: Box, + reader: Option> +} + +impl InputStream where R: Read + Seek { + fn new(reader: R) -> Self { + let mut boxed_reader = Box::new(reader); + let stream = Self { + raw: Box::new(WMPStream { + state: WMPStream__bindgen_ty_1 { + pvObj: boxed_reader.as_mut() as *mut R as *mut c_void, + }, + fMem: 0, + Close: Some(Self::input_stream_close), + EOS: None, // Not used in library code base! + Read: Some(Self::input_stream_read), + Write: Some(Self::input_stream_write), + SetPos: Some(Self::input_stream_set_pos), + GetPos: Some(Self::input_stream_get_pos) + }), + reader: Some(boxed_reader) + }; + stream + } + + pub fn into_reader(mut self) -> R { + let mut reader: Option> = None; + std::mem::swap(&mut reader, &mut self.reader); + *reader.unwrap() + } + + unsafe fn get_reader(me: *mut WMPStream) -> *mut R { + std::mem::transmute((*me).state.pvObj) + } + + unsafe extern "C" fn input_stream_close(_me: *mut *mut WMPStream) -> ERR { + // Do nothing -- we'll free the reader from the Rust side + WMP_errSuccess as ERR + } + + unsafe extern "C" fn input_stream_read(me: *mut WMPStream, dest: *mut c_void, cb: usize) -> ERR { + let reader = Self::get_reader(me); + let bytes: *mut u8 = std::mem::transmute(dest); + let dest_slice = std::slice::from_raw_parts_mut(bytes, cb); + match (*reader).read_exact(dest_slice) { + Ok(_) => WMP_errSuccess as ERR, + Err(_) => WMP_errFileIO as ERR + } + } + + unsafe extern "C" fn input_stream_write(_me: *mut WMPStream, _dest: *const c_void, _cb: usize) -> ERR { + WMP_errFileIO as ERR + } + + unsafe extern "C" fn input_stream_set_pos(me: *mut WMPStream, off_pos: usize) -> ERR { + let reader = Self::get_reader(me); + match (*reader).seek(SeekFrom::Start(off_pos as u64)) { + Ok(_) => WMP_errSuccess as ERR, + Err(_) => WMP_errFileIO as ERR + } + } + + unsafe extern "C" fn input_stream_get_pos(me: *mut WMPStream, off_pos: *mut usize) -> ERR { + let reader = Self::get_reader(me); + match (*reader).stream_position() { + Ok(pos) => { + match usize::try_from(pos) { + Ok(out) => { + *off_pos = out; + WMP_errSuccess as ERR + }, + Err(_) => WMP_errFileIO as ERR + } + }, + Err(_) => WMP_errFileIO as ERR + } + } +} + +/// +/// Coordinate struct for reading a subset of an image. +/// Pixels are i32. +/// +pub struct Rect { + raw: PKRect +} + +impl Rect { + /// + /// Create a Rect with the given coordinates. + /// + pub fn new(x: i32, y: i32, width: i32, height: i32) -> Self { + Self { + raw: PKRect { + X: x, + Y: y, + Width: width, + Height: height + } + } + } + + /// + /// Get the X offset. + /// + pub fn get_x(&self) -> i32 { + self.raw.X + } + + /// + /// Get the Y offset. + /// + pub fn get_y(&self) -> i32 { + self.raw.Y + } + + /// + /// Get the width. + /// + pub fn get_width(&self) -> i32 { + self.raw.Width + } + + /// + /// Get the height, in pixels + /// + pub fn get_height(&self) -> i32 { + self.raw.Height + } +} + +/// +/// High-level JPEG XR image decoder struct. +/// Requires a seekable data source, such as a File. +/// You can decode multiple subsets of the image, +/// though this is not yet well-tested. +/// +pub struct ImageDecode { + raw: *mut PKImageDecode, + stream: Option>, +} + +impl ImageDecode where R: Read + Seek { + + /// + /// Create a new JPEG XR image decoder for the given input. + /// This will consume the reader, and free it when done. + /// + pub fn with_reader(reader: R) -> Result { + unsafe { + let mut stream = InputStream::new(reader); + + let mut codec: *mut PKImageDecode = std::ptr::null_mut(); + call(PKImageDecode_Create_WMP(&mut codec as *mut *mut PKImageDecode))?; + call((*codec).Initialize.unwrap()(codec, stream.raw.as_mut()))?; + + Ok(Self { + raw: codec, + stream: Some(stream) + }) + } + } + + /// + /// Return the pixel format of the decoded image. + /// This is just a big enum; you're responsible for knowing how to + /// interpret the image data yourself from that. + /// This could fail if a new unknown pixel type appears in the wild. + /// + pub fn get_pixel_format(&self) -> Result { + unsafe { + let mut guid: GUID = std::mem::zeroed(); + call((*self.raw).GetPixelFormat.unwrap()(self.raw, &mut guid))?; + PixelFormat::from_guid(&guid) + } + } + + /// + /// Get width and height in pixels. + /// + pub fn get_size(&self) -> Result<(i32, i32)> { + unsafe { + let mut width: i32 = 0; + let mut height: i32 = 0; + call((*self.raw).GetSize.unwrap()(self.raw, &mut width, &mut height))?; + Ok((width, height)) + } + } + + /// + /// Get horizontal and vertical DPI. + /// + pub fn get_resolution(&self) -> Result<(f32, f32)> { + unsafe { + let mut horiz: f32 = 0.0; + let mut vert: f32 = 0.0; + call((*self.raw).GetResolution.unwrap()(self.raw, &mut horiz, &mut vert))?; + Ok((horiz, vert)) + } + } + + /// + /// Decode pixel data and copy it into a provided output buffer. + /// You can ask for just part of the image to decode fewer macroblocks. + /// However this mode is not well tested. + /// + pub fn copy(&mut self, rect: &Rect, dest: &mut [u8], stride: usize) -> Result<()> { + let stride_u32 = u32::try_from(stride)?; + unsafe { + call((*self.raw).Copy.unwrap()(self.raw, &rect.raw, dest.as_mut_ptr(), stride_u32))?; + Ok(()) + } + } + + /// + /// Decode the entire image in one go, for convenience. + /// + pub fn copy_all(&mut self, dest: &mut [u8], stride: usize) -> Result<()> { + let (width, height) = self.get_size()?; + let rect = Rect::new(0, 0, width, height); + self.copy(&rect, dest, stride) + } + + /// + /// Free the image decoder and return the input reader. + /// Only needed if you want to reuse the same reader struct + /// on something else, but it feels so Rustic! + /// + pub fn into_reader(mut self) -> R { + let mut stream: Option> = None; + std::mem::swap(&mut stream, &mut self.stream); + stream.unwrap().into_reader() + } +} + +impl Drop for ImageDecode where R: Read + Seek { + fn drop(&mut self) { + unsafe { + // Release the C structure. + (*self.raw).Release.unwrap()(&mut self.raw); + } + } +} + +#[cfg(test)] +mod tests { + use std::fs::{File}; + use crate::ImageDecode; + use crate::PixelFormat::*; + use crate::PixelInfo; + use crate::ColorFormat; + use crate::BitDepthBits; + use crate::PhotometricInterpretation; + + #[test] + fn it_works() { + let input_result = File::open("samples/panel-hdr.jxr"); + assert!(input_result.is_ok()); + let input = input_result.unwrap(); + + let decoder_result = ImageDecode::with_reader(input); + assert!(decoder_result.is_ok()); + let decoder = decoder_result.unwrap(); + + let size_result = decoder.get_size(); + assert!(size_result.is_ok()); + let (width, height) = size_result.unwrap(); + assert_eq!(width, 3440); + assert_eq!(height, 1440); + + let pixfmt_result = decoder.get_pixel_format(); + assert!(pixfmt_result.is_ok()); + let pixfmt = pixfmt_result.unwrap(); + assert_eq!(pixfmt, PixelFormat128bppRGBAFloat); + + let info = PixelInfo::from_format(pixfmt); + assert_eq!(info.channels(), 4); + assert_eq!(info.color_format(), ColorFormat::RGB); + assert_eq!(info.bit_depth(), BitDepthBits::ThirtyTwoF); + assert!(info.has_alpha()); + assert!(!info.premultiplied_alpha()); + assert!(!info.bgr()); + assert_eq!(info.photometric_interpretation(), PhotometricInterpretation::RGB); + assert_eq!(info.samples_per_pixel(), 4); + } +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/wasm/test.js b/packages/jxr/dist/codec/node_modules/jpegxr/wasm/test.js new file mode 100644 index 0000000..9db0cef --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/wasm/test.js @@ -0,0 +1,29 @@ +let fs = require('fs'); +let jpegxr = require('./jpegxr.js'); + +jpegxr().then((codec) => { + console.log(codec); + let bytes = fs.readFileSync('samples/panel-hdr.jxr'); + let image = codec.decode(bytes); + console.log(image); + + let floats = new Float32Array(image.bytes.buffer); + let red_sum = 0.0; + let green_sum = 0.0; + let blue_sum = 0.0; + for (let y = 0; y < image.height; y++) { + for (let x = 0; x < image.width; x++) { + let i = x * 4 + y * image.width * 4; + red_sum += floats[i]; + green_sum += floats[i + 1]; + blue_sum += floats[i + 2]; + } + } + let count = (image.width * image.height); + let red_avg = red_sum / count; + let green_avg = green_sum / count; + let blue_avg = blue_sum / count; + console.log('average red brightness: ' + red_avg); + console.log('average green brightness: ' + green_avg); + console.log('average blue brightness: ' + blue_avg); +}); diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/wasm/wasm_api.c b/packages/jxr/dist/codec/node_modules/jpegxr/wasm/wasm_api.c new file mode 100644 index 0000000..fa3fb13 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/wasm/wasm_api.c @@ -0,0 +1,170 @@ +#include +#include +#include "JXRGlue.h" + +EMSCRIPTEN_KEEPALIVE +PKPixelInfo *pixel_info_from_guid(GUID* guid) +{ + PKPixelInfo *info = (PKPixelInfo *)malloc(sizeof(PKPixelInfo)); + info->pGUIDPixFmt = guid; + if (PixelFormatLookup(info, LOOKUP_FORWARD)) { + return NULL; + } + return info; +} + +EMSCRIPTEN_KEEPALIVE +void pixel_info_free(PKPixelInfo* info) +{ + free(info); +} + +EMSCRIPTEN_KEEPALIVE +size_t pixel_info_channels(PKPixelInfo* info) +{ + return info->cChannel; +} + +EMSCRIPTEN_KEEPALIVE +const char *pixel_info_color_format(const PKPixelInfo* info) +{ + switch (info->cfColorFormat) { + case Y_ONLY: return "YOnly"; + case YUV_420: return "YUV420"; + case YUV_422: return "YUV422"; + case YUV_444: return "YUV4444"; + case CMYK: return "CMYK"; + case NCOMPONENT: return "NComponent"; + case CF_RGB: return "RGB"; + case CF_RGBE: return "RGBE"; + default: return NULL; + } +} + +EMSCRIPTEN_KEEPALIVE +const char *pixel_info_bit_depth(const PKPixelInfo* info) +{ + switch (info->bdBitDepth) { + case BD_1: return "1"; //White is foreground + case BD_8: return "8"; + case BD_16: return "16"; + case BD_16S: return "16Fixed"; + case BD_16F: return "16Float"; + case BD_32: return "32"; + case BD_32S: return "32Fixed"; + case BD_32F: return "32Float"; + case BD_5: return "5"; + case BD_10: return "10"; + case BD_565: return "565"; + case BD_1alt: return "1alt"; //Black is foreground + default: return NULL; + } +} + +EMSCRIPTEN_KEEPALIVE +size_t pixel_info_bits_per_pixel(const PKPixelInfo* info) +{ + return info->cbitUnit; +} + +EMSCRIPTEN_KEEPALIVE +bool pixel_info_has_alpha(const PKPixelInfo* info) +{ + return (info->grBit & PK_pixfmtHasAlpha) != 0; +} + +EMSCRIPTEN_KEEPALIVE +bool pixel_info_premultiplied_alpha(const PKPixelInfo* info) +{ + return (info->grBit & PK_pixfmtPreMul) != 0; +} + +EMSCRIPTEN_KEEPALIVE +bool pixel_info_bgr(const PKPixelInfo* info) +{ + return (info->grBit & PK_pixfmtBGR) != 0; +} + + +EMSCRIPTEN_KEEPALIVE +unsigned pixel_info_photometric_interpretation(const PKPixelInfo* info) +{ + // @fixme map to string + return info->uInterpretation; +} + +EMSCRIPTEN_KEEPALIVE +size_t pixel_info_samples_per_pixel(const PKPixelInfo* info) +{ + return info->uSamplePerPixel; +} + +EMSCRIPTEN_KEEPALIVE +PKImageDecode *image_decode_with_memory(void *buffer, size_t bytes) +{ + struct WMPStream *stream; + if (CreateWS_Memory(&stream, buffer, bytes)) { + return NULL; + } + PKImageDecode *decode; + if (PKImageDecode_Create_WMP(&decode)) { + stream->Close(&stream); + return NULL; + } + if (decode->Initialize(decode, stream)) { + decode->Release(&decode); + stream->Close(&stream); + return NULL; + } + return decode; +} + +EMSCRIPTEN_KEEPALIVE +PKPixelInfo* image_decode_pixel_info(PKImageDecode *decode) +{ + GUID guid; + if (decode->GetPixelFormat(decode, &guid)) { + return NULL; + } + return pixel_info_from_guid(&guid); +} + +EMSCRIPTEN_KEEPALIVE +int image_decode_width(PKImageDecode *decode) +{ + int width, height; + if (decode->GetSize(decode, &width, &height)) { + return -1; + } + return width; +} + +EMSCRIPTEN_KEEPALIVE +int image_decode_height(PKImageDecode *decode) +{ + int width, height; + if (decode->GetSize(decode, &width, &height)) { + return -1; + } + return height; +} + +EMSCRIPTEN_KEEPALIVE +int image_decode_copy_all(PKImageDecode *decode, void *dest, size_t stride) +{ + int width, height; + if (decode->GetSize(decode, &width, &height)) { + return -1; + } + PKRect rect = { 0, 0, width, height }; + if (decode->Copy(decode, &rect, dest, stride)) { + return -1; + } + return 0; +} + +EMSCRIPTEN_KEEPALIVE +void image_decode_free(PKImageDecode *decode) +{ + decode->Release(&decode); +} diff --git a/packages/jxr/dist/codec/node_modules/jpegxr/wasm/wasm_api.js b/packages/jxr/dist/codec/node_modules/jpegxr/wasm/wasm_api.js new file mode 100644 index 0000000..3f85057 --- /dev/null +++ b/packages/jxr/dist/codec/node_modules/jpegxr/wasm/wasm_api.js @@ -0,0 +1,77 @@ +// Override the default return value with a cleaner API +Module.readyOrig = Module.ready; +Module.ready = Module.readyOrig.then(() => { + return { + decode: function(bytesIn) { + if (!(bytesIn instanceof Uint8Array)) { + throw new Error("Expected Uint8Array") + } + + let sizeIn = bytesIn.length; + let bufferIn = Module._malloc(sizeIn); + if (bufferIn == 0) { + throw new Error("Failed to allocate buffer"); + } + try { + HEAPU8.set(bytesIn, bufferIn); + + let imageDecode = Module._image_decode_with_memory(bufferIn, sizeIn); + if (imageDecode == 0) { + throw new Error("Failed to initialize ImageDecode"); + } + try { + let width = Module._image_decode_width(imageDecode); + let height = Module._image_decode_height(imageDecode); + let pixelInfo = Module._image_decode_pixel_info(imageDecode); + if (pixelInfo == 0) { + throw new Error("Failed to get PixelInfo") + } + try { + let channels = Module._pixel_info_channels(pixelInfo); + let colorFormat = UTF8ToString(Module._pixel_info_color_format(pixelInfo)); + let bitDepth = UTF8ToString(Module._pixel_info_bit_depth(pixelInfo)); + let bitsPerPixel = Module._pixel_info_bits_per_pixel(pixelInfo); + let hasAlpha = !!Module._pixel_info_has_alpha(pixelInfo); + let premultipledAlpha = !!Module._pixel_info_premultiplied_alpha(pixelInfo); + let bgr = !!Module._pixel_info_bgr(pixelInfo); + + let sizeOut = width * height * bitsPerPixel / 8; + let bufferOut = Module._malloc(sizeOut); + if (bufferOut == 0) { + throw new Error("Failed to allocate output buffer"); + } + try { + if (Module._image_decode_copy_all(imageDecode, bufferOut, width * bitsPerPixel / 8) < 0) { + throw new Error("Failed to decode image"); + } + // Copy the output bytes to a fresh Uint8Array + let bytesOut = HEAPU8.slice(bufferOut, bufferOut + sizeOut); + return { + width, + height, + pixelInfo: { + channels, + colorFormat, + bitDepth, + bitsPerPixel, + hasAlpha, + premultipledAlpha, + bgr, + }, + bytes: bytesOut, + }; + } finally { + Module._free(bufferOut); + } + } finally { + Module._pixel_info_free(pixelInfo); + } + } finally { + Module._image_decode_free(imageDecode); + } + } finally { + Module._free(bufferIn); + } + } + }; +}); diff --git a/packages/jxr/dist/codec/package.json b/packages/jxr/dist/codec/package.json new file mode 100644 index 0000000..1105641 --- /dev/null +++ b/packages/jxr/dist/codec/package.json @@ -0,0 +1,6 @@ +{ + "scripts": { + "build": "docker run --rm -v \"$PWD\":/src alpine sh -c \"find /src -name '*.o' -delete\" && EMSDK_VERSION=3.1.57 DEFAULT_CFLAGS='-Oz -flto' ../../../tools/build-cpp.sh" + }, + "type": "module" +} diff --git a/packages/jxr/dist/codec/pre.js b/packages/jxr/dist/codec/pre.js new file mode 100644 index 0000000..073dd63 --- /dev/null +++ b/packages/jxr/dist/codec/pre.js @@ -0,0 +1,24 @@ +const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; +const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; +const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; + +if (isRunningInCloudFlareWorkers || isRunningInNode) { + if (!globalThis.ImageData) { + // Simple Polyfill for ImageData Object + globalThis.ImageData = class ImageData { + constructor(data, width, height) { + this.data = data; + this.width = width; + this.height = height; + } + }; + } + + if (import.meta.url === undefined) { + import.meta.url = 'https://localhost'; + } + + if (typeof self !== 'undefined' && self.location === undefined) { + self.location = { href: '' }; + } +} diff --git a/packages/jxr/dist/decode.d.ts b/packages/jxr/dist/decode.d.ts new file mode 100644 index 0000000..d6ab2ae --- /dev/null +++ b/packages/jxr/dist/decode.d.ts @@ -0,0 +1,3 @@ +export declare function init(moduleOptionOverrides?: Partial): Promise; +export default function decode(buffer: ArrayBuffer): Promise; +//# sourceMappingURL=decode.d.ts.map \ No newline at end of file diff --git a/packages/jxr/dist/decode.d.ts.map b/packages/jxr/dist/decode.d.ts.map new file mode 100644 index 0000000..245e798 --- /dev/null +++ b/packages/jxr/dist/decode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../decode.ts"],"names":[],"mappings":"AAOA,wBAAsB,IAAI,CACxB,qBAAqB,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC,CAAC;AAqBjB,wBAA8B,MAAM,CAClC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,SAAS,CAAC,CASpB"} \ No newline at end of file diff --git a/packages/jxr/dist/decode.js b/packages/jxr/dist/decode.js new file mode 100644 index 0000000..1a25318 --- /dev/null +++ b/packages/jxr/dist/decode.js @@ -0,0 +1,22 @@ +import { initEmscriptenModule } from './utils.js'; +import jxr_dec from './codec/dec/jxr_dec.js'; +let emscriptenModule; +export async function init(module, moduleOptionOverrides) { + let actualModule = module; + let actualOptions = moduleOptionOverrides; + if (arguments.length === 1 && !(module instanceof WebAssembly.Module)) { + actualModule = undefined; + actualOptions = module; + } + emscriptenModule = initEmscriptenModule(jxr_dec, actualModule, actualOptions); +} +export default async function decode(buffer) { + if (!emscriptenModule) { + init(); + } + const module = await emscriptenModule; + const result = module.decode(buffer); + if (!result) + throw new Error('Decoding error'); + return result; +} diff --git a/packages/jxr/dist/emscripten-types.d.ts b/packages/jxr/dist/emscripten-types.d.ts new file mode 100644 index 0000000..690ce36 --- /dev/null +++ b/packages/jxr/dist/emscripten-types.d.ts @@ -0,0 +1,137 @@ +// These types roughly model the object that the JS files generated by Emscripten define. Copied from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/emscripten/index.d.ts and turned into a type definition rather than a global to support our way of using Emscripten. +// TODO(@surma): Upstream this? +declare namespace EmscriptenWasm { + type ModuleFactory = ( + moduleOverrides?: ModuleOpts, + ) => Promise; + + type EnvironmentType = 'WEB' | 'NODE' | 'SHELL' | 'WORKER'; + + // Options object for modularized Emscripten files. Shoe-horned by @surma. + // FIXME: This an incomplete definition! + interface ModuleOpts { + mainScriptUrlOrBlob?: string; + noInitialRun?: boolean; + locateFile?: + | ((path: string) => string) + | ((path: string, prefix: string) => string); + onRuntimeInitialized?: () => void; + instantiateWasm?: ( + imports: WebAssembly.Imports, + successCallback: (module: WebAssembly.Module) => void, + ) => WebAssembly.Exports; + } + + interface Module { + print(str: string): void; + printErr(str: string): void; + arguments: string[]; + environment: EnvironmentType; + preInit: { (): void }[]; + preRun: { (): void }[]; + postRun: { (): void }[]; + preinitializedWebGLContext: WebGLRenderingContext; + noInitialRun: boolean; + noExitRuntime: boolean; + logReadFiles: boolean; + filePackagePrefixURL: string; + wasmBinary: ArrayBuffer; + + destroy(object: object): void; + getPreloadedPackage( + remotePackageName: string, + remotePackageSize: number, + ): ArrayBuffer; + instantiateWasm( + imports: WebAssembly.Imports, + successCallback: (module: WebAssembly.Module) => void, + ): WebAssembly.Exports; + locateFile(url: string): string; + onCustomMessage(event: MessageEvent): void; + + Runtime: any; + + ccall( + ident: string, + returnType: string | null, + argTypes: string[], + args: any[], + ): any; + cwrap(ident: string, returnType: string | null, argTypes: string[]): any; + + setValue(ptr: number, value: any, type: string, noSafe?: boolean): void; + getValue(ptr: number, type: string, noSafe?: boolean): number; + + ALLOC_NORMAL: number; + ALLOC_STACK: number; + ALLOC_STATIC: number; + ALLOC_DYNAMIC: number; + ALLOC_NONE: number; + + allocate(slab: any, types: string, allocator: number, ptr: number): number; + allocate( + slab: any, + types: string[], + allocator: number, + ptr: number, + ): number; + + Pointer_stringify(ptr: number, length?: number): string; + UTF16ToString(ptr: number): string; + stringToUTF16(str: string, outPtr: number): void; + UTF32ToString(ptr: number): string; + stringToUTF32(str: string, outPtr: number): void; + + // USE_TYPED_ARRAYS == 1 + HEAP: Int32Array; + IHEAP: Int32Array; + FHEAP: Float64Array; + + // USE_TYPED_ARRAYS == 2 + HEAP8: Int8Array; + HEAP16: Int16Array; + HEAP32: Int32Array; + HEAPU8: Uint8Array; + HEAPU16: Uint16Array; + HEAPU32: Uint32Array; + HEAPF32: Float32Array; + HEAPF64: Float64Array; + + TOTAL_STACK: number; + TOTAL_MEMORY: number; + FAST_MEMORY: number; + + addOnPreRun(cb: () => any): void; + addOnInit(cb: () => any): void; + addOnPreMain(cb: () => any): void; + addOnExit(cb: () => any): void; + addOnPostRun(cb: () => any): void; + + // Tools + intArrayFromString( + stringy: string, + dontAddNull?: boolean, + length?: number, + ): number[]; + intArrayToString(array: number[]): string; + writeStringToMemory( + str: string, + buffer: number, + dontAddNull: boolean, + ): void; + writeArrayToMemory(array: number[], buffer: number): void; + writeAsciiToMemory(str: string, buffer: number, dontAddNull: boolean): void; + + addRunDependency(id: any): void; + removeRunDependency(id: any): void; + + preloadedImages: any; + preloadedAudios: any; + + _malloc(size: number): number; + _free(ptr: number): void; + + // Augmentations below by @surma. + onRuntimeInitialized: () => void | null; + } +} diff --git a/packages/jxr/dist/index.d.ts b/packages/jxr/dist/index.d.ts new file mode 100644 index 0000000..67e9e4c --- /dev/null +++ b/packages/jxr/dist/index.d.ts @@ -0,0 +1,2 @@ +export { default as decode } from './decode.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/packages/jxr/dist/index.d.ts.map b/packages/jxr/dist/index.d.ts.map new file mode 100644 index 0000000..67f5d71 --- /dev/null +++ b/packages/jxr/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/packages/jxr/dist/index.js b/packages/jxr/dist/index.js new file mode 100644 index 0000000..3ed6443 --- /dev/null +++ b/packages/jxr/dist/index.js @@ -0,0 +1 @@ +export { default as decode } from './decode.js'; diff --git a/packages/jxr/dist/meta.d.ts b/packages/jxr/dist/meta.d.ts new file mode 100644 index 0000000..d089134 --- /dev/null +++ b/packages/jxr/dist/meta.d.ts @@ -0,0 +1,4 @@ +export declare const label = "JPEG XR"; +export declare const mimeType = "image/vnd.ms-photo"; +export declare const extension = "jxr"; +//# sourceMappingURL=meta.d.ts.map \ No newline at end of file diff --git a/packages/jxr/dist/meta.d.ts.map b/packages/jxr/dist/meta.d.ts.map new file mode 100644 index 0000000..8c036f7 --- /dev/null +++ b/packages/jxr/dist/meta.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../meta.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,QAAQ,uBAAuB,CAAC;AAC7C,eAAO,MAAM,SAAS,QAAQ,CAAC"} \ No newline at end of file diff --git a/packages/jxr/dist/meta.js b/packages/jxr/dist/meta.js new file mode 100644 index 0000000..856509c --- /dev/null +++ b/packages/jxr/dist/meta.js @@ -0,0 +1,3 @@ +export const label = 'JPEG XR'; +export const mimeType = 'image/vnd.ms-photo'; +export const extension = 'jxr'; diff --git a/packages/jxr/dist/package.json b/packages/jxr/dist/package.json new file mode 100644 index 0000000..5e47760 --- /dev/null +++ b/packages/jxr/dist/package.json @@ -0,0 +1,35 @@ +{ + "name": "@jsquash/jxr", + "version": "1.0.0", + "main": "index.js", + "description": "Wasm JPEG XR decoder supporting the browser.", + "repository": "jamsinclair/jSquash", + "author": { + "name": "Jamie Sinclair", + "email": "jamsinclairnz+npm@gmail.com" + }, + "keywords": [ + "image", + "optimisation", + "optimization", + "squoosh", + "wasm", + "webassembly", + "jxr", + "jpeg-xr", + "jpegxr" + ], + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf dist", + "build:codec": "cd codec && npm run build", + "build": "npm run clean && tsc && cp -r codec package.json README.md *.d.ts .npmignore ../../LICENSE dist && cd dist/codec", + "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" + }, + "devDependencies": { + "@types/node": "^20.9.2", + "typescript": "^4.4.4" + }, + "type": "module", + "sideEffects": false +} diff --git a/packages/jxr/dist/tsconfig.tsbuildinfo b/packages/jxr/dist/tsconfig.tsbuildinfo new file mode 100644 index 0000000..bd617e1 --- /dev/null +++ b/packages/jxr/dist/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../node_modules/typescript/lib/lib.dom.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../../node_modules/typescript/lib/lib.scripthost.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/typescript/lib/lib.es2019.full.d.ts","../codec/dec/jxr_dec.d.ts","../utils.ts","../decode.ts","../emscripten-types.d.ts","../index.ts","../meta.ts","../../../node_modules/@types/json-schema/index.d.ts","../../../node_modules/@types/json5/index.d.ts","../../../node_modules/@types/node/compatibility/disposable.d.ts","../../../node_modules/@types/node/compatibility/indexable.d.ts","../../../node_modules/@types/node/compatibility/iterators.d.ts","../../../node_modules/@types/node/compatibility/index.d.ts","../../../node_modules/@types/node/globals.typedarray.d.ts","../../../node_modules/@types/node/buffer.buffer.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../../node_modules/@types/node/web-globals/domexception.d.ts","../../../node_modules/@types/node/web-globals/events.d.ts","../../../node_modules/undici-types/header.d.ts","../../../node_modules/undici-types/readable.d.ts","../../../node_modules/undici-types/file.d.ts","../../../node_modules/undici-types/fetch.d.ts","../../../node_modules/undici-types/formdata.d.ts","../../../node_modules/undici-types/connector.d.ts","../../../node_modules/undici-types/client.d.ts","../../../node_modules/undici-types/errors.d.ts","../../../node_modules/undici-types/dispatcher.d.ts","../../../node_modules/undici-types/global-dispatcher.d.ts","../../../node_modules/undici-types/global-origin.d.ts","../../../node_modules/undici-types/pool-stats.d.ts","../../../node_modules/undici-types/pool.d.ts","../../../node_modules/undici-types/handlers.d.ts","../../../node_modules/undici-types/balanced-pool.d.ts","../../../node_modules/undici-types/agent.d.ts","../../../node_modules/undici-types/mock-interceptor.d.ts","../../../node_modules/undici-types/mock-agent.d.ts","../../../node_modules/undici-types/mock-client.d.ts","../../../node_modules/undici-types/mock-pool.d.ts","../../../node_modules/undici-types/mock-errors.d.ts","../../../node_modules/undici-types/proxy-agent.d.ts","../../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../../node_modules/undici-types/retry-handler.d.ts","../../../node_modules/undici-types/retry-agent.d.ts","../../../node_modules/undici-types/api.d.ts","../../../node_modules/undici-types/interceptors.d.ts","../../../node_modules/undici-types/util.d.ts","../../../node_modules/undici-types/cookies.d.ts","../../../node_modules/undici-types/patch.d.ts","../../../node_modules/undici-types/websocket.d.ts","../../../node_modules/undici-types/eventsource.d.ts","../../../node_modules/undici-types/filereader.d.ts","../../../node_modules/undici-types/diagnostics-channel.d.ts","../../../node_modules/undici-types/content-type.d.ts","../../../node_modules/undici-types/cache.d.ts","../../../node_modules/undici-types/index.d.ts","../../../node_modules/@types/node/web-globals/fetch.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.generated.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/readline/promises.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/sea.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/index.d.ts","../../../node_modules/@types/semver/functions/inc.d.ts","../../../node_modules/@types/semver/classes/semver.d.ts","../../../node_modules/@types/semver/functions/parse.d.ts","../../../node_modules/@types/semver/functions/valid.d.ts","../../../node_modules/@types/semver/functions/clean.d.ts","../../../node_modules/@types/semver/functions/diff.d.ts","../../../node_modules/@types/semver/functions/major.d.ts","../../../node_modules/@types/semver/functions/minor.d.ts","../../../node_modules/@types/semver/functions/patch.d.ts","../../../node_modules/@types/semver/functions/prerelease.d.ts","../../../node_modules/@types/semver/functions/compare.d.ts","../../../node_modules/@types/semver/functions/rcompare.d.ts","../../../node_modules/@types/semver/functions/compare-loose.d.ts","../../../node_modules/@types/semver/functions/compare-build.d.ts","../../../node_modules/@types/semver/functions/sort.d.ts","../../../node_modules/@types/semver/functions/rsort.d.ts","../../../node_modules/@types/semver/functions/gt.d.ts","../../../node_modules/@types/semver/functions/lt.d.ts","../../../node_modules/@types/semver/functions/eq.d.ts","../../../node_modules/@types/semver/functions/neq.d.ts","../../../node_modules/@types/semver/functions/gte.d.ts","../../../node_modules/@types/semver/functions/lte.d.ts","../../../node_modules/@types/semver/functions/cmp.d.ts","../../../node_modules/@types/semver/functions/coerce.d.ts","../../../node_modules/@types/semver/classes/comparator.d.ts","../../../node_modules/@types/semver/classes/range.d.ts","../../../node_modules/@types/semver/functions/satisfies.d.ts","../../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../../node_modules/@types/semver/ranges/min-version.d.ts","../../../node_modules/@types/semver/ranges/valid.d.ts","../../../node_modules/@types/semver/ranges/outside.d.ts","../../../node_modules/@types/semver/ranges/gtr.d.ts","../../../node_modules/@types/semver/ranges/ltr.d.ts","../../../node_modules/@types/semver/ranges/intersects.d.ts","../../../node_modules/@types/semver/ranges/simplify.d.ts","../../../node_modules/@types/semver/ranges/subset.d.ts","../../../node_modules/@types/semver/internals/identifiers.d.ts","../../../node_modules/@types/semver/index.d.ts"],"fileIdsList":[[65,111],[65,108,111],[65,110,111],[111],[65,111,116,144],[65,111,112,117,122,130,141,152],[65,111,112,113,122,130],[60,61,62,65,111],[65,111,114,153],[65,111,115,116,123,131],[65,111,116,141,149],[65,111,117,119,122,130],[65,110,111,118],[65,111,119,120],[65,111,121,122],[65,110,111,122],[65,111,122,123,124,141,152],[65,111,122,123,124,137,141,144],[65,111,119,122,125,130,141,152],[65,111,122,123,125,126,130,141,149,152],[65,111,125,127,141,149,152],[63,64,65,66,67,68,69,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158],[65,111,122,128],[65,111,129,152,157],[65,111,119,122,130,141],[65,111,131],[65,111,132],[65,110,111,133],[65,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158],[65,111,135],[65,111,136],[65,111,122,137,138],[65,111,137,139,153,155],[65,111,122,141,142,144],[65,111,143,144],[65,111,141,142],[65,111,144],[65,111,145],[65,108,111,141,146],[65,111,122,147,148],[65,111,147,148],[65,111,116,130,141,149],[65,111,150],[65,111,130,151],[65,111,125,136,152],[65,111,116,153],[65,111,141,154],[65,111,129,155],[65,111,156],[65,106,111],[65,106,111,122,124,133,141,144,152,155,157],[65,111,141,158],[65,111,161,199],[65,111,161,184,199],[65,111,160,199],[65,111,199],[65,111,161],[65,111,161,185,199],[65,111,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198],[65,111,185,199],[65,78,82,111,152],[65,78,111,141,152],[65,73,111],[65,75,78,111,149,152],[65,111,130,149],[65,111,159],[65,73,111,159],[65,75,78,111,130,152],[65,70,71,74,77,111,122,141,152],[65,78,85,111],[65,70,76,111],[65,78,99,100,111],[65,74,78,111,144,152,159],[65,99,111,159],[65,72,73,111,159],[65,78,111],[65,72,73,74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,100,101,102,103,104,105,111],[65,78,93,111],[65,78,85,86,111],[65,76,78,86,87,111],[65,77,111],[65,70,73,78,111],[65,78,82,86,87,111],[65,82,111],[65,76,78,81,111,152],[65,70,75,78,85,111],[65,111,141],[65,73,78,99,111,157,159],[52,53,65,111],[54,65,111]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7a3c8b952931daebdfc7a2897c53c0a1c73624593fa070e46bd537e64dcd20a","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"08f6861df84fba9719c14d5adc3ba40be9f0c687639e6c4df3c05b9301b8ff94","impliedFormat":1},"535c01ab085a7a296fe32ea4cae6a126a6ed373f7cf8bc201718f81d34352b13",{"version":"376ba715ecb04eba8ff70a5dde58b95e98303e8118bf99933bfdd0b9b6a1ee7f","signature":"515ae5616ac4fe9dcf7ef21fa8294961e2bd950fb36ca34bc003a3de44fe5d8c"},{"version":"28600f05f1d5b458d569c6bc38e94900930c6cb29dc8b0e61042dc7622346582","signature":"7f8c5961dcec2cb2b2e6d95969de9ed36973968e4c56ad1e184841bb02efbe70"},{"version":"acc5de7ea6c944da8709c50a8ea0d7bb0a2c2a62db61c6f1dc1f248e876b1b40","affectsGlobalScope":true},"5394bb5c78af7ba3ffac95c30d8f916a297e8cbb7c1f8bd53e95c9269c0516ea",{"version":"99b8d13c12f3ae02201edb65e8317a4f96ad56c7957c7ff12812396cd7784fd0","signature":"aedb303f99e37ad37da3e3510ee16ad92b7c9584bdfe872f9a21dd06363e75ee"},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","impliedFormat":1},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"ba481bca06f37d3f2c137ce343c7d5937029b2468f8e26111f3c9d9963d6568d","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d9ef24f9a22a88e3e9b3b3d8c40ab1ddb0853f1bfbd5c843c37800138437b61","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"e2677634fe27e87348825bb041651e22d50a613e2fdf6a4a3ade971d71bac37e","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"8cd19276b6590b3ebbeeb030ac271871b9ed0afc3074ac88a94ed2449174b776","affectsGlobalScope":true,"impliedFormat":1},{"version":"696eb8d28f5949b87d894b26dc97318ef944c794a9a4e4f62360cd1d1958014b","impliedFormat":1},{"version":"3f8fa3061bd7402970b399300880d55257953ee6d3cd408722cb9ac20126460c","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"68bd56c92c2bd7d2339457eb84d63e7de3bd56a69b25f3576e1568d21a162398","affectsGlobalScope":true,"impliedFormat":1},{"version":"3e93b123f7c2944969d291b35fed2af79a6e9e27fdd5faa99748a51c07c02d28","impliedFormat":1},{"version":"9d19808c8c291a9010a6c788e8532a2da70f811adb431c97520803e0ec649991","impliedFormat":1},{"version":"87aad3dd9752067dc875cfaa466fc44246451c0c560b820796bdd528e29bef40","impliedFormat":1},{"version":"4aacb0dd020eeaef65426153686cc639a78ec2885dc72ad220be1d25f1a439df","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"8db0ae9cb14d9955b14c214f34dae1b9ef2baee2fe4ce794a4cd3ac2531e3255","affectsGlobalScope":true,"impliedFormat":1},{"version":"15fc6f7512c86810273af28f224251a5a879e4261b4d4c7e532abfbfc3983134","impliedFormat":1},{"version":"58adba1a8ab2d10b54dc1dced4e41f4e7c9772cbbac40939c0dc8ce2cdb1d442","impliedFormat":1},{"version":"641942a78f9063caa5d6b777c99304b7d1dc7328076038c6d94d8a0b81fc95c1","impliedFormat":1},{"version":"714435130b9015fae551788df2a88038471a5a11eb471f27c4ede86552842bc9","impliedFormat":1},{"version":"855cd5f7eb396f5f1ab1bc0f8580339bff77b68a770f84c6b254e319bbfd1ac7","impliedFormat":1},{"version":"5650cf3dace09e7c25d384e3e6b818b938f68f4e8de96f52d9c5a1b3db068e86","impliedFormat":1},{"version":"1354ca5c38bd3fd3836a68e0f7c9f91f172582ba30ab15bb8c075891b91502b7","affectsGlobalScope":true,"impliedFormat":1},{"version":"7e20d899c28ca26a2a7afc98beaa69e63ff7fba0a8bc47b4e3bf3ede5e09e424","impliedFormat":1},{"version":"2d2fcaab481b31a5882065c7951255703ddbe1c0e507af56ea42d79ac3911201","impliedFormat":1},{"version":"a192fe8ec33f75edbc8d8f3ed79f768dfae11ff5735e7fe52bfa69956e46d78d","impliedFormat":1},{"version":"ca867399f7db82df981d6915bcbb2d81131d7d1ef683bc782b59f71dda59bc85","affectsGlobalScope":true,"impliedFormat":1},{"version":"372413016d17d804e1d139418aca0c68e47a83fb6669490857f4b318de8cccb3","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"6e70e9570e98aae2b825b533aa6292b6abd542e8d9f6e9475e88e1d7ba17c866","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"085f552d005479e2e6a7311cdbbe5d8c55c497b4d19274285df161ee9684cd9c","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"007faacc9268357caa21d24169f3f3f2497af3e9241308df2d89f6e6d9bb3f2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"74cf591a0f63db318651e0e04cb55f8791385f86e987a67fd4d2eaab8191f730","impliedFormat":1},{"version":"5eab9b3dc9b34f185417342436ec3f106898da5f4801992d8ff38ab3aff346b5","impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"809821b8a065e3234a55b3a9d7846231ed18d66dd749f2494c66288d890daf7f","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"c3b41e74b9a84b88b1dca61ec39eee25c0dbc8e7d519ba11bb070918cfacf656","affectsGlobalScope":true,"impliedFormat":1},{"version":"4737a9dc24d0e68b734e6cfbcea0c15a2cfafeb493485e27905f7856988c6b29","affectsGlobalScope":true,"impliedFormat":1},{"version":"36d8d3e7506b631c9582c251a2c0b8a28855af3f76719b12b534c6edf952748d","impliedFormat":1},{"version":"1ca69210cc42729e7ca97d3a9ad48f2e9cb0042bada4075b588ae5387debd318","impliedFormat":1},{"version":"f5ebe66baaf7c552cfa59d75f2bfba679f329204847db3cec385acda245e574e","impliedFormat":1},{"version":"ed59add13139f84da271cafd32e2171876b0a0af2f798d0c663e8eeb867732cf","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7c5e2ea4a9749097c347454805e933844ed207b6eefec6b7cfd418b5f5f7b28","impliedFormat":1},{"version":"b1810689b76fd473bd12cc9ee219f8e62f54a7d08019a235d07424afbf074d25","impliedFormat":1},{"version":"ce6a3f09b8db73a7e9701aca91a04b4fabaf77436dd35b24482f9ee816016b17","impliedFormat":1},{"version":"20e086e5b64fdd52396de67761cc0e94693494deadb731264aac122adf08de3f","impliedFormat":1},{"version":"6e78f75403b3ec65efb41c70d392aeda94360f11cedc9fb2c039c9ea23b30962","impliedFormat":1},{"version":"c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","impliedFormat":1},{"version":"8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","impliedFormat":1},{"version":"42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","impliedFormat":1},{"version":"ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","impliedFormat":1},{"version":"83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","impliedFormat":1},{"version":"1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","impliedFormat":1},{"version":"0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","impliedFormat":1},{"version":"cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","impliedFormat":1},{"version":"c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","impliedFormat":1},{"version":"eefd2bbc8edb14c3bd1246794e5c070a80f9b8f3730bd42efb80df3cc50b9039","impliedFormat":1},{"version":"0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","impliedFormat":1},{"version":"7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","impliedFormat":1},{"version":"bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","impliedFormat":1},{"version":"52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","impliedFormat":1},{"version":"770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","impliedFormat":1},{"version":"d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","impliedFormat":1},{"version":"799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","impliedFormat":1},{"version":"2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","impliedFormat":1},{"version":"9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","impliedFormat":1},{"version":"397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","impliedFormat":1},{"version":"a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","impliedFormat":1},{"version":"a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","impliedFormat":1},{"version":"c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","impliedFormat":1},{"version":"4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","impliedFormat":1},{"version":"f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","impliedFormat":1},{"version":"cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","impliedFormat":1},{"version":"b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","impliedFormat":1},{"version":"c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","impliedFormat":1},{"version":"14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","impliedFormat":1},{"version":"a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","impliedFormat":1},{"version":"f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","impliedFormat":1},{"version":"3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","impliedFormat":1},{"version":"662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","impliedFormat":1},{"version":"c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","impliedFormat":1},{"version":"2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","impliedFormat":1},{"version":"34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","impliedFormat":1},{"version":"a56fe175741cc8841835eb72e61fa5a34adcbc249ede0e3494c229f0750f6b85","impliedFormat":1}],"root":[[52,57]],"options":{"allowSyntheticDefaultImports":true,"composite":true,"declarationMap":true,"downlevelIteration":true,"jsx":2,"module":99,"outDir":"./","rootDir":"..","strict":true,"target":6},"referencedMap":[[58,1],[59,1],[108,2],[109,2],[110,3],[65,4],[111,5],[112,6],[113,7],[60,1],[63,8],[61,1],[62,1],[114,9],[115,10],[116,11],[117,12],[118,13],[119,14],[120,14],[121,15],[122,16],[123,17],[124,18],[66,1],[64,1],[125,19],[126,20],[127,21],[159,22],[128,23],[129,24],[130,25],[131,26],[132,27],[133,28],[134,29],[135,30],[136,31],[137,32],[138,32],[139,33],[140,1],[141,34],[143,35],[142,36],[144,37],[145,38],[146,39],[147,40],[148,41],[149,42],[150,43],[151,44],[152,45],[153,46],[154,47],[155,48],[156,49],[67,1],[68,1],[69,1],[107,50],[157,51],[158,52],[184,53],[185,54],[161,55],[164,56],[182,53],[183,53],[173,53],[172,57],[170,53],[165,53],[178,53],[176,53],[180,53],[160,53],[177,53],[181,53],[166,53],[167,53],[179,53],[162,53],[168,53],[169,53],[171,53],[175,53],[186,58],[174,53],[163,53],[199,59],[198,1],[193,58],[195,60],[194,58],[187,58],[188,58],[190,58],[192,58],[196,60],[197,60],[189,60],[191,60],[49,1],[50,1],[10,1],[8,1],[9,1],[14,1],[13,1],[2,1],[15,1],[16,1],[17,1],[18,1],[19,1],[20,1],[21,1],[22,1],[3,1],[23,1],[24,1],[4,1],[25,1],[29,1],[26,1],[27,1],[28,1],[30,1],[31,1],[32,1],[5,1],[33,1],[34,1],[35,1],[36,1],[6,1],[51,1],[40,1],[37,1],[38,1],[39,1],[41,1],[7,1],[42,1],[47,1],[48,1],[43,1],[44,1],[45,1],[46,1],[1,1],[12,1],[11,1],[85,61],[95,62],[84,61],[105,63],[76,64],[75,65],[104,66],[98,67],[103,68],[78,69],[92,70],[77,71],[101,72],[73,73],[72,66],[102,74],[74,75],[79,76],[80,1],[83,76],[70,1],[106,77],[96,78],[87,79],[88,80],[90,81],[86,82],[89,83],[99,66],[81,84],[82,85],[91,86],[71,87],[94,78],[93,76],[97,1],[100,88],[52,1],[54,89],[55,1],[56,90],[57,1],[53,1]],"latestChangedDtsFile":"./meta.d.ts","version":"5.9.3"} \ No newline at end of file diff --git a/packages/jxr/dist/utils.d.ts b/packages/jxr/dist/utils.d.ts new file mode 100644 index 0000000..c79976b --- /dev/null +++ b/packages/jxr/dist/utils.d.ts @@ -0,0 +1,17 @@ +/** + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module. + */ +export declare function initEmscriptenModule(moduleFactory: EmscriptenWasm.ModuleFactory, wasmModule?: WebAssembly.Module, moduleOptionOverrides?: Partial): Promise; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/packages/jxr/dist/utils.d.ts.map b/packages/jxr/dist/utils.d.ts.map new file mode 100644 index 0000000..926b22e --- /dev/null +++ b/packages/jxr/dist/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;GAEG;AAEH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,cAAc,CAAC,MAAM,EAClE,aAAa,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,EAC9C,UAAU,CAAC,EAAE,WAAW,CAAC,MAAM,EAC/B,qBAAqB,GAAE,OAAO,CAAC,cAAc,CAAC,UAAU,CAAM,GAC7D,OAAO,CAAC,CAAC,CAAC,CAmBZ"} \ No newline at end of file diff --git a/packages/jxr/dist/utils.js b/packages/jxr/dist/utils.js new file mode 100644 index 0000000..dc7ff29 --- /dev/null +++ b/packages/jxr/dist/utils.js @@ -0,0 +1,30 @@ +/** + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module. + */ +export function initEmscriptenModule(moduleFactory, wasmModule, moduleOptionOverrides = {}) { + let instantiateWasm; + if (wasmModule) { + instantiateWasm = (imports, callback) => { + const instance = new WebAssembly.Instance(wasmModule, imports); + callback(instance); + return instance.exports; + }; + } + return moduleFactory({ + noInitialRun: true, + instantiateWasm, + ...moduleOptionOverrides, + }); +} diff --git a/packages/jxr/emscripten-types.d.ts b/packages/jxr/emscripten-types.d.ts new file mode 100644 index 0000000..690ce36 --- /dev/null +++ b/packages/jxr/emscripten-types.d.ts @@ -0,0 +1,137 @@ +// These types roughly model the object that the JS files generated by Emscripten define. Copied from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/emscripten/index.d.ts and turned into a type definition rather than a global to support our way of using Emscripten. +// TODO(@surma): Upstream this? +declare namespace EmscriptenWasm { + type ModuleFactory = ( + moduleOverrides?: ModuleOpts, + ) => Promise; + + type EnvironmentType = 'WEB' | 'NODE' | 'SHELL' | 'WORKER'; + + // Options object for modularized Emscripten files. Shoe-horned by @surma. + // FIXME: This an incomplete definition! + interface ModuleOpts { + mainScriptUrlOrBlob?: string; + noInitialRun?: boolean; + locateFile?: + | ((path: string) => string) + | ((path: string, prefix: string) => string); + onRuntimeInitialized?: () => void; + instantiateWasm?: ( + imports: WebAssembly.Imports, + successCallback: (module: WebAssembly.Module) => void, + ) => WebAssembly.Exports; + } + + interface Module { + print(str: string): void; + printErr(str: string): void; + arguments: string[]; + environment: EnvironmentType; + preInit: { (): void }[]; + preRun: { (): void }[]; + postRun: { (): void }[]; + preinitializedWebGLContext: WebGLRenderingContext; + noInitialRun: boolean; + noExitRuntime: boolean; + logReadFiles: boolean; + filePackagePrefixURL: string; + wasmBinary: ArrayBuffer; + + destroy(object: object): void; + getPreloadedPackage( + remotePackageName: string, + remotePackageSize: number, + ): ArrayBuffer; + instantiateWasm( + imports: WebAssembly.Imports, + successCallback: (module: WebAssembly.Module) => void, + ): WebAssembly.Exports; + locateFile(url: string): string; + onCustomMessage(event: MessageEvent): void; + + Runtime: any; + + ccall( + ident: string, + returnType: string | null, + argTypes: string[], + args: any[], + ): any; + cwrap(ident: string, returnType: string | null, argTypes: string[]): any; + + setValue(ptr: number, value: any, type: string, noSafe?: boolean): void; + getValue(ptr: number, type: string, noSafe?: boolean): number; + + ALLOC_NORMAL: number; + ALLOC_STACK: number; + ALLOC_STATIC: number; + ALLOC_DYNAMIC: number; + ALLOC_NONE: number; + + allocate(slab: any, types: string, allocator: number, ptr: number): number; + allocate( + slab: any, + types: string[], + allocator: number, + ptr: number, + ): number; + + Pointer_stringify(ptr: number, length?: number): string; + UTF16ToString(ptr: number): string; + stringToUTF16(str: string, outPtr: number): void; + UTF32ToString(ptr: number): string; + stringToUTF32(str: string, outPtr: number): void; + + // USE_TYPED_ARRAYS == 1 + HEAP: Int32Array; + IHEAP: Int32Array; + FHEAP: Float64Array; + + // USE_TYPED_ARRAYS == 2 + HEAP8: Int8Array; + HEAP16: Int16Array; + HEAP32: Int32Array; + HEAPU8: Uint8Array; + HEAPU16: Uint16Array; + HEAPU32: Uint32Array; + HEAPF32: Float32Array; + HEAPF64: Float64Array; + + TOTAL_STACK: number; + TOTAL_MEMORY: number; + FAST_MEMORY: number; + + addOnPreRun(cb: () => any): void; + addOnInit(cb: () => any): void; + addOnPreMain(cb: () => any): void; + addOnExit(cb: () => any): void; + addOnPostRun(cb: () => any): void; + + // Tools + intArrayFromString( + stringy: string, + dontAddNull?: boolean, + length?: number, + ): number[]; + intArrayToString(array: number[]): string; + writeStringToMemory( + str: string, + buffer: number, + dontAddNull: boolean, + ): void; + writeArrayToMemory(array: number[], buffer: number): void; + writeAsciiToMemory(str: string, buffer: number, dontAddNull: boolean): void; + + addRunDependency(id: any): void; + removeRunDependency(id: any): void; + + preloadedImages: any; + preloadedAudios: any; + + _malloc(size: number): number; + _free(ptr: number): void; + + // Augmentations below by @surma. + onRuntimeInitialized: () => void | null; + } +} diff --git a/packages/jxr/index.ts b/packages/jxr/index.ts new file mode 100644 index 0000000..3ed6443 --- /dev/null +++ b/packages/jxr/index.ts @@ -0,0 +1 @@ +export { default as decode } from './decode.js'; diff --git a/packages/jxr/meta.ts b/packages/jxr/meta.ts new file mode 100644 index 0000000..856509c --- /dev/null +++ b/packages/jxr/meta.ts @@ -0,0 +1,3 @@ +export const label = 'JPEG XR'; +export const mimeType = 'image/vnd.ms-photo'; +export const extension = 'jxr'; diff --git a/packages/jxr/package.json b/packages/jxr/package.json new file mode 100644 index 0000000..5e47760 --- /dev/null +++ b/packages/jxr/package.json @@ -0,0 +1,35 @@ +{ + "name": "@jsquash/jxr", + "version": "1.0.0", + "main": "index.js", + "description": "Wasm JPEG XR decoder supporting the browser.", + "repository": "jamsinclair/jSquash", + "author": { + "name": "Jamie Sinclair", + "email": "jamsinclairnz+npm@gmail.com" + }, + "keywords": [ + "image", + "optimisation", + "optimization", + "squoosh", + "wasm", + "webassembly", + "jxr", + "jpeg-xr", + "jpegxr" + ], + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf dist", + "build:codec": "cd codec && npm run build", + "build": "npm run clean && tsc && cp -r codec package.json README.md *.d.ts .npmignore ../../LICENSE dist && cd dist/codec", + "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" + }, + "devDependencies": { + "@types/node": "^20.9.2", + "typescript": "^4.4.4" + }, + "type": "module", + "sideEffects": false +} diff --git a/packages/jxr/tsconfig.json b/packages/jxr/tsconfig.json new file mode 100644 index 0000000..7de4869 --- /dev/null +++ b/packages/jxr/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2019", + "downlevelIteration": true, + "module": "esnext", + "jsx": "react", + "jsxFactory": "h", + "strict": true, + "moduleResolution": "node", + "composite": true, + "declarationMap": true, + "baseUrl": "./", + "rootDir": "./", + "outDir": "dist", + "allowSyntheticDefaultImports": true + } +} diff --git a/packages/jxr/utils.ts b/packages/jxr/utils.ts new file mode 100644 index 0000000..f6e0e69 --- /dev/null +++ b/packages/jxr/utils.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module. + */ + +export function initEmscriptenModule( + moduleFactory: EmscriptenWasm.ModuleFactory, + wasmModule?: WebAssembly.Module, + moduleOptionOverrides: Partial = {}, +): Promise { + let instantiateWasm; + + if (wasmModule) { + instantiateWasm = ( + imports: WebAssembly.Imports, + callback: (instance: WebAssembly.Instance) => void, + ) => { + const instance = new WebAssembly.Instance(wasmModule, imports); + callback(instance); + return instance.exports; + }; + } + + return moduleFactory({ + noInitialRun: true, + instantiateWasm, + ...moduleOptionOverrides, + }); +}