ranger-compiler 3.5.0 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1160 -19
- package/LICENSE +3 -1
- package/README.md +124 -29
- package/dist/Lang.rgr +1188 -290
- package/dist/api.d.ts +2343 -879
- package/dist/api.js +79924 -56922
- package/dist/lib/JSON.rgr +102 -91
- package/dist/lib/Shell.rgr +4 -4
- package/dist/lib/apple/AppleToolchain.rgr +4 -4
- package/dist/lib/apple/README.md +5 -4
- package/dist/lib/apple/apple_test.rgr +1 -1
- package/dist/lib/core/README.md +1 -1
- package/dist/lib/evg/EVG.rgr +12 -0
- package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
- package/dist/lib/evg/EVGA11yTree.rgr +894 -0
- package/dist/lib/evg/EVGBox.rgr +267 -0
- package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
- package/dist/lib/evg/EVGCodepoint.rgr +316 -0
- package/dist/lib/evg/EVGColor.rgr +700 -0
- package/dist/lib/evg/EVGCommands.rgr +177 -0
- package/dist/lib/evg/EVGComponent.rgr +331 -0
- package/dist/lib/evg/EVGComponentTest.rgr +387 -0
- package/dist/lib/evg/EVGConnector.rgr +541 -0
- package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
- package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
- package/dist/lib/evg/EVGEasing.rgr +370 -0
- package/dist/lib/evg/EVGEffectTest.rgr +253 -0
- package/dist/lib/evg/EVGElement.rgr +4914 -0
- package/dist/lib/evg/EVGFixedTest.rgr +289 -0
- package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
- package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
- package/dist/lib/evg/EVGFling.rgr +244 -0
- package/dist/lib/evg/EVGFocus.rgr +400 -0
- package/dist/lib/evg/EVGFocusTest.rgr +399 -0
- package/dist/lib/evg/EVGGradient.rgr +322 -0
- package/dist/lib/evg/EVGGrapheme.rgr +190 -0
- package/dist/lib/evg/EVGGrid.rgr +975 -0
- package/dist/lib/evg/EVGHitTest.rgr +208 -0
- package/dist/lib/evg/EVGHoles.rgr +294 -0
- package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
- package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
- package/dist/lib/evg/EVGHostTree.rgr +834 -0
- package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
- package/dist/lib/evg/EVGImageDecode.rgr +117 -0
- package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
- package/dist/lib/evg/EVGInspect.rgr +883 -0
- package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
- package/dist/lib/evg/EVGJsonTest.rgr +535 -0
- package/dist/lib/evg/EVGLayout.rgr +4220 -0
- package/dist/lib/evg/EVGMeasure.rgr +1267 -0
- package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
- package/dist/lib/evg/EVGPatch.rgr +1721 -0
- package/dist/lib/evg/EVGPatchTest.rgr +692 -0
- package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
- package/dist/lib/evg/EVGReconcile.rgr +226 -0
- package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
- package/dist/lib/evg/EVGReject.rgr +126 -0
- package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
- package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
- package/dist/lib/evg/EVGRuler.rgr +232 -0
- package/dist/lib/evg/EVGRulerTest.rgr +172 -0
- package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
- package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
- package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
- package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
- package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
- package/dist/lib/evg/EVGText.rgr +105 -0
- package/dist/lib/evg/EVGTextEngine.rgr +536 -0
- package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
- package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
- package/dist/lib/evg/EVGToolbar.rgr +1369 -0
- package/dist/lib/evg/EVGTransition.rgr +728 -0
- package/dist/lib/evg/EVGTreeJson.rgr +721 -0
- package/dist/lib/evg/EVGUnit.rgr +554 -0
- package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
- package/dist/lib/evg/EvgApp.rgr +189 -0
- package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
- package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
- package/dist/lib/evg/EvgHost.rgr +451 -0
- package/dist/lib/evg/EvgTest.rgr +91 -0
- package/dist/lib/evg/EvgTraceColor.rgr +236 -0
- package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
- package/dist/lib/evg/EvgTraceFit.rgr +767 -0
- package/dist/lib/evg/EvgTracePath.rgr +435 -0
- package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
- package/dist/lib/evg/EvgViewport.rgr +313 -0
- package/dist/lib/evg/FxDemoDoc.rgr +185 -0
- package/dist/lib/evg/HOSTS.md +227 -0
- package/dist/lib/evg/ISSUES.md +835 -0
- package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
- package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
- package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
- package/dist/lib/evg/PLAN_EVG.md +518 -0
- package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
- package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
- package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
- package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
- package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
- package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
- package/dist/lib/evg/PathBuilder.rgr +333 -0
- package/dist/lib/evg/README.md +1236 -0
- package/dist/lib/evg/SPEC.md +1252 -0
- package/dist/lib/evg/SVGPathParser.rgr +1199 -0
- package/dist/lib/evg/SvgParser.rgr +1736 -0
- package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
- package/dist/lib/evg/VectorShapes.rgr +331 -0
- package/dist/lib/evg/VectorStroke.rgr +107 -0
- package/dist/lib/evg/VectorViewBox.rgr +380 -0
- package/dist/lib/evg/agent/README.md +290 -0
- package/dist/lib/evg/agent/evg_agent.rgr +899 -0
- package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
- package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
- package/dist/lib/evg/agent/fixtures/connector.css +63 -0
- package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
- package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
- package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
- package/dist/lib/evg/agent/fixtures/popover.css +99 -0
- package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
- package/dist/lib/evg/agent/roundtrip.sh +74 -0
- package/dist/lib/evg/agent/smoke.sh +230 -0
- package/dist/lib/evg/android/README.md +97 -0
- package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
- package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
- package/dist/lib/evg/android/androidstubs/App.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
- package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
- package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
- package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
- package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
- package/dist/lib/evg/android/androidstubs/View.kt +113 -0
- package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
- package/dist/lib/evg/apple/README.md +128 -0
- package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
- package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
- package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
- package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
- package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
- package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
- package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
- package/dist/lib/evg/bench/README.md +64 -0
- package/dist/lib/evg/bench/layout-bench.mjs +316 -0
- package/dist/lib/evg/bench/layout-cases.mjs +510 -0
- package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
- package/dist/lib/evg/bin/.gitignore +17 -0
- package/dist/lib/evg/evg_test.rgr +313 -0
- package/dist/lib/evg/gl/README.md +198 -0
- package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
- package/dist/lib/evg/gl/blur-check.mjs +399 -0
- package/dist/lib/evg/gl/boxmodel.json +1 -0
- package/dist/lib/evg/gl/demo.html +46 -0
- package/dist/lib/evg/gl/effect-presets.css +285 -0
- package/dist/lib/evg/gl/effect-presets.js +63 -0
- package/dist/lib/evg/gl/effect-shots.mjs +135 -0
- package/dist/lib/evg/gl/evg-a11y.js +566 -0
- package/dist/lib/evg/gl/evg-binary.js +160 -0
- package/dist/lib/evg/gl/evg-engine.js +296 -0
- package/dist/lib/evg/gl/evg-fx.js +237 -0
- package/dist/lib/evg/gl/evg-gestures.js +209 -0
- package/dist/lib/evg/gl/evg-list.js +167 -0
- package/dist/lib/evg/gl/evg-measure.js +186 -0
- package/dist/lib/evg/gl/evg-textinput.js +303 -0
- package/dist/lib/evg/gl/evg-view.js +144 -0
- package/dist/lib/evg/gl/evg-webgl.js +3942 -0
- package/dist/lib/evg/gl/fx-check.mjs +998 -0
- package/dist/lib/evg/gl/fx-demo.html +166 -0
- package/dist/lib/evg/gl/fx-demo.js +2 -0
- package/dist/lib/evg/gl/fx-serve.mjs +47 -0
- package/dist/lib/evg/gl/gestures-check.mjs +189 -0
- package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
- package/dist/lib/evg/gl/measure-check.mjs +135 -0
- package/dist/lib/evg/gl/rotation-check.mjs +207 -0
- package/dist/lib/evg/gl/shift-check.mjs +113 -0
- package/dist/lib/evg/gl/stroke-check.mjs +168 -0
- package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
- package/dist/lib/evg/gl/view-check.mjs +343 -0
- package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
- package/dist/lib/evg/html/evg-dom.js +318 -0
- package/dist/lib/evg/html/evg-html.js +600 -0
- package/dist/lib/evg/inspect/README.md +415 -0
- package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
- package/dist/lib/evg/inspect/evg-inspect.js +947 -0
- package/dist/lib/evg/inspect/shots/css.png +0 -0
- package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
- package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
- package/dist/lib/evg/inspect/shots/state.png +0 -0
- package/dist/lib/evg/inspect/shots.mjs +226 -0
- package/dist/lib/evg/oracle/css-blur.json +576 -0
- package/dist/lib/evg/oracle/css-box.json +157 -0
- package/dist/lib/evg/oracle/css-timing.json +709 -0
- package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
- package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
- package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
- package/dist/lib/evg/original/EVGColor.clj +310 -0
- package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
- package/dist/lib/evg/original/SVGPath.rgr +627 -0
- package/dist/lib/evg/original/Vec2.crgr +103 -0
- package/dist/lib/evg/ranger.json +9 -0
- package/dist/lib/evg/showcase/README.md +246 -0
- package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
- package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
- package/dist/lib/evg/showcase/build.mjs +651 -0
- package/dist/lib/evg/showcase/pages/album.tsx +30 -0
- package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
- package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
- package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
- package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
- package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
- package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
- package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
- package/dist/lib/evg/showcase/pages/more.tsx +332 -0
- package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
- package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
- package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
- package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
- package/dist/lib/evg/showcase/pages/units.tsx +35 -0
- package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
- package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
- package/dist/lib/evg/showcase/pages/views.tsx +223 -0
- package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
- package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
- package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
- package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
- package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
- package/dist/lib/evg/showcase/themes/more-default.css +128 -0
- package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
- package/dist/lib/evg/showcase/themes/showcase.css +508 -0
- package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
- package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
- package/dist/lib/evg/showcase/themes/views-default.css +15 -0
- package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
- package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
- package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
- package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
- package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
- package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
- package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
- package/dist/lib/evg/web/responsive/README.md +97 -0
- package/dist/lib/evg/web/responsive/build.mjs +90 -0
- package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
- package/dist/lib/evg/web/responsive/index.html +177 -0
- package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
- package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
- package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
- package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
- package/dist/lib/evg/web/tools/minify.mjs +60 -0
- package/dist/lib/evg/web/tracer/build.mjs +87 -0
- package/dist/lib/evg/web/tracer/index.html +2805 -0
- package/dist/lib/evg/web/tracer/sample.png +0 -0
- package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
- package/dist/lib/evgr/Cargo.lock +21 -0
- package/dist/lib/evgr/Cargo.toml +19 -0
- package/dist/lib/evgr/README.md +140 -0
- package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
- package/dist/lib/evgr/bench/compare.mjs +252 -0
- package/dist/lib/evgr/bench/speed.mjs +277 -0
- package/dist/lib/evgr/bin/.gitignore +3 -0
- package/dist/lib/evgr/src/bin/bench.rs +106 -0
- package/dist/lib/evgr/src/bin/smoke.rs +13 -0
- package/dist/lib/evgr/src/grid.rs +730 -0
- package/dist/lib/evgr/src/lib.rs +1003 -0
- package/dist/lib/evgr/src/style.rs +468 -0
- package/dist/lib/evgr/src/text.rs +83 -0
- package/dist/lib/image/BitReader.rgr +171 -0
- package/dist/lib/image/Buffer.rgr +173 -0
- package/dist/lib/image/DCT.rgr +283 -0
- package/dist/lib/image/Deflate.rgr +339 -0
- package/dist/lib/image/HuffmanDecoder.rgr +181 -0
- package/dist/lib/image/ImageBuffer.rgr +706 -0
- package/dist/lib/image/JPEGDecoder.rgr +808 -0
- package/dist/lib/image/PNGDecoder.rgr +544 -0
- package/dist/lib/image/PNGEncoder.rgr +388 -0
- package/dist/lib/image/PPMImage.rgr +224 -0
- package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
- package/dist/lib/image/README.md +33 -0
- package/dist/lib/image/RasterBuffer.rgr +294 -0
- package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
- package/dist/lib/image/WebPDecoder.rgr +433 -0
- package/dist/lib/image/WebPLossless.rgr +1035 -0
- package/dist/lib/image/WebPLossy.rgr +1929 -0
- package/dist/lib/image/ranger.json +9 -0
- package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
- package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
- package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
- package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
- package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
- package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
- package/dist/lib/image/tests/run_webp_tests.sh +39 -0
- package/dist/lib/rust/RsJson.rgr +468 -0
- package/dist/lib/rust/RsPrelude.rgr +1663 -0
- package/dist/lib/shell_test.rgr +7 -7
- package/dist/lib/stdlib.rgr +21 -5
- package/dist/lib/zip/ranger.json +6 -0
- package/dist/rgrc.js +87318 -67610
- package/package.json +1010 -1040
- package/dist/README.md +0 -117
- package/dist/package.json +0 -47
|
@@ -0,0 +1,1154 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; ProgressiveJPEGDecoder.rgr - Progressive JPEG decoder
|
|
4
|
+
; Progressive JPEG uses multiple scans to refine image quality
|
|
5
|
+
|
|
6
|
+
Import "Buffer.rgr"
|
|
7
|
+
Import "BitReader.rgr"
|
|
8
|
+
Import "HuffmanDecoder.rgr"
|
|
9
|
+
Import "DCT.rgr"
|
|
10
|
+
Import "ImageBuffer.rgr"
|
|
11
|
+
Import "JPEGDecoder.rgr"
|
|
12
|
+
|
|
13
|
+
; Wrapper class for coefficient array (to allow array of arrays)
|
|
14
|
+
class CoeffBuffer {
|
|
15
|
+
def coeffs:[int]
|
|
16
|
+
def numBlocks:int 0
|
|
17
|
+
|
|
18
|
+
Constructor () {
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
fn init:void (blocks:int) {
|
|
22
|
+
numBlocks = blocks
|
|
23
|
+
clear coeffs
|
|
24
|
+
def numCoeffs:int (blocks * 64)
|
|
25
|
+
def i 0
|
|
26
|
+
while (i < numCoeffs) {
|
|
27
|
+
push coeffs 0
|
|
28
|
+
i = i + 1
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fn get:int (blockIdx:int k:int) {
|
|
33
|
+
def offset:int ((blockIdx * 64) + k)
|
|
34
|
+
return (at coeffs offset)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fn setVal:void (blockIdx:int k:int value:int) {
|
|
38
|
+
def offset:int ((blockIdx * 64) + k)
|
|
39
|
+
set coeffs offset value
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class ProgressiveJPEGDecoder {
|
|
44
|
+
; A picture is decoded because something is being DRAWN, not because
|
|
45
|
+
; anybody asked about the JPEG — the same reason `JPEGDecoder` has this.
|
|
46
|
+
; Twenty-four lines of narration per photograph is noise, and on a native
|
|
47
|
+
; host it is noise on somebody's terminal.
|
|
48
|
+
def quiet:boolean false
|
|
49
|
+
def data:buffer (buffer_alloc 0)
|
|
50
|
+
def dataLen:int 0
|
|
51
|
+
|
|
52
|
+
; Image properties
|
|
53
|
+
def width:int 0
|
|
54
|
+
def height:int 0
|
|
55
|
+
def numComponents:int 0
|
|
56
|
+
def precision:int 8
|
|
57
|
+
def isProgressive:boolean false
|
|
58
|
+
|
|
59
|
+
; Components
|
|
60
|
+
def components:[JPEGComponent]
|
|
61
|
+
|
|
62
|
+
; Quantization tables (up to 4)
|
|
63
|
+
def quantTables:[QuantizationTable]
|
|
64
|
+
|
|
65
|
+
; Huffman decoder
|
|
66
|
+
def huffman:HuffmanDecoder (new HuffmanDecoder())
|
|
67
|
+
|
|
68
|
+
; DCT transformer
|
|
69
|
+
def idct:IDCT (new IDCT())
|
|
70
|
+
|
|
71
|
+
; MCU dimensions
|
|
72
|
+
def mcuWidth:int 8
|
|
73
|
+
def mcuHeight:int 8
|
|
74
|
+
def mcusPerRow:int 0
|
|
75
|
+
def mcusPerCol:int 0
|
|
76
|
+
def maxHSamp:int 1
|
|
77
|
+
def maxVSamp:int 1
|
|
78
|
+
|
|
79
|
+
; Progressive coefficient storage
|
|
80
|
+
def coeffBuffers:[CoeffBuffer]
|
|
81
|
+
|
|
82
|
+
; Scan parameters
|
|
83
|
+
def scanSs:int 0
|
|
84
|
+
def scanSe:int 63
|
|
85
|
+
def scanAh:int 0
|
|
86
|
+
def scanAl:int 0
|
|
87
|
+
|
|
88
|
+
; EOBRUN for AC successive approximation
|
|
89
|
+
def eobrun:int 0
|
|
90
|
+
|
|
91
|
+
Constructor () {
|
|
92
|
+
huffman = (new HuffmanDecoder())
|
|
93
|
+
idct = (new IDCT())
|
|
94
|
+
|
|
95
|
+
def i 0
|
|
96
|
+
while (i < 4) {
|
|
97
|
+
push quantTables (new QuantizationTable())
|
|
98
|
+
i = i + 1
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
fn readUint16BE:int (pos:int) {
|
|
103
|
+
def high:int (buffer_get data pos)
|
|
104
|
+
def low:int (buffer_get data (pos + 1))
|
|
105
|
+
return ((high * 256) + low)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
fn parseSOF:void (pos:int length:int sofType:int) {
|
|
109
|
+
precision = (buffer_get data pos)
|
|
110
|
+
height = (this.readUint16BE(pos + 1))
|
|
111
|
+
width = (this.readUint16BE(pos + 3))
|
|
112
|
+
numComponents = (buffer_get data (pos + 5))
|
|
113
|
+
|
|
114
|
+
if (sofType == 2) {
|
|
115
|
+
isProgressive = true
|
|
116
|
+
if (quiet == false) {
|
|
117
|
+
print (" Progressive JPEG: " + (to_string width) + "x" + (to_string height) + ", " + (to_string numComponents) + " components")
|
|
118
|
+
}
|
|
119
|
+
} {
|
|
120
|
+
isProgressive = false
|
|
121
|
+
if (quiet == false) {
|
|
122
|
+
print (" Baseline JPEG: " + (to_string width) + "x" + (to_string height) + ", " + (to_string numComponents) + " components")
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
clear components
|
|
127
|
+
maxHSamp = 1
|
|
128
|
+
maxVSamp = 1
|
|
129
|
+
|
|
130
|
+
def i 0
|
|
131
|
+
def offset:int (pos + 6)
|
|
132
|
+
while (i < numComponents) {
|
|
133
|
+
def comp (new JPEGComponent())
|
|
134
|
+
comp.id = (buffer_get data offset)
|
|
135
|
+
def sampling:int (buffer_get data (offset + 1))
|
|
136
|
+
comp.hSamp = (bit_shr sampling 4)
|
|
137
|
+
comp.vSamp = (bit_and sampling 15)
|
|
138
|
+
comp.quantTableId = (buffer_get data (offset + 2))
|
|
139
|
+
|
|
140
|
+
if (comp.hSamp > maxHSamp) { maxHSamp = comp.hSamp }
|
|
141
|
+
if (comp.vSamp > maxVSamp) { maxVSamp = comp.vSamp }
|
|
142
|
+
|
|
143
|
+
push components comp
|
|
144
|
+
if (quiet == false) {
|
|
145
|
+
print (" Component " + (to_string comp.id) + ": " + (to_string comp.hSamp) + "x" + (to_string comp.vSamp) + " sampling")
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
offset = offset + 3
|
|
149
|
+
i = i + 1
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
mcuWidth = maxHSamp * 8
|
|
153
|
+
mcuHeight = maxVSamp * 8
|
|
154
|
+
mcusPerRow = (to_int ((width + mcuWidth - 1) / mcuWidth))
|
|
155
|
+
mcusPerCol = (to_int ((height + mcuHeight - 1) / mcuHeight))
|
|
156
|
+
|
|
157
|
+
if (quiet == false) {
|
|
158
|
+
print (" MCU grid: " + (to_string mcusPerRow) + "x" + (to_string mcusPerCol))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this.allocateCoeffBuffers()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
fn allocateCoeffBuffers:void () {
|
|
165
|
+
clear coeffBuffers
|
|
166
|
+
def totalMCUs:int (mcusPerRow * mcusPerCol)
|
|
167
|
+
|
|
168
|
+
def c 0
|
|
169
|
+
while (c < numComponents) {
|
|
170
|
+
def comp:JPEGComponent (at components c)
|
|
171
|
+
def blocksInComp:int (totalMCUs * comp.hSamp * comp.vSamp)
|
|
172
|
+
|
|
173
|
+
def buf (new CoeffBuffer())
|
|
174
|
+
buf.init(blocksInComp)
|
|
175
|
+
push coeffBuffers buf
|
|
176
|
+
|
|
177
|
+
c = c + 1
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
fn parseDQT:void (pos:int length:int) {
|
|
182
|
+
def endPos:int (pos + length)
|
|
183
|
+
|
|
184
|
+
while (pos < endPos) {
|
|
185
|
+
def info:int (buffer_get data pos)
|
|
186
|
+
pos = pos + 1
|
|
187
|
+
|
|
188
|
+
def prec:int (bit_shr info 4)
|
|
189
|
+
def tableId:int (bit_and info 15)
|
|
190
|
+
|
|
191
|
+
def table:QuantizationTable (at quantTables tableId)
|
|
192
|
+
table.id = tableId
|
|
193
|
+
clear table.values
|
|
194
|
+
|
|
195
|
+
def i 0
|
|
196
|
+
while (i < 64) {
|
|
197
|
+
if (prec == 0) {
|
|
198
|
+
push table.values (buffer_get data pos)
|
|
199
|
+
pos = pos + 1
|
|
200
|
+
} {
|
|
201
|
+
push table.values (this.readUint16BE(pos))
|
|
202
|
+
pos = pos + 2
|
|
203
|
+
}
|
|
204
|
+
i = i + 1
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (quiet == false) {
|
|
208
|
+
print (" Quantization table " + (to_string tableId))
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
fn parseSOS:int (pos:int length:int) {
|
|
214
|
+
def numScanComponents:int (buffer_get data pos)
|
|
215
|
+
pos = pos + 1
|
|
216
|
+
|
|
217
|
+
def scanComponents:[int]
|
|
218
|
+
|
|
219
|
+
def i 0
|
|
220
|
+
while (i < numScanComponents) {
|
|
221
|
+
def compId:int (buffer_get data pos)
|
|
222
|
+
def tableSelect:int (buffer_get data (pos + 1))
|
|
223
|
+
pos = pos + 2
|
|
224
|
+
|
|
225
|
+
def j 0
|
|
226
|
+
while (j < numComponents) {
|
|
227
|
+
def comp:JPEGComponent (at components j)
|
|
228
|
+
if (comp.id == compId) {
|
|
229
|
+
comp.dcTableId = (bit_shr tableSelect 4)
|
|
230
|
+
comp.acTableId = (bit_and tableSelect 15)
|
|
231
|
+
push scanComponents j
|
|
232
|
+
}
|
|
233
|
+
j = j + 1
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
i = i + 1
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
scanSs = (buffer_get data pos)
|
|
240
|
+
scanSe = (buffer_get data (pos + 1))
|
|
241
|
+
def approx:int (buffer_get data (pos + 2))
|
|
242
|
+
scanAh = (bit_shr approx 4)
|
|
243
|
+
scanAl = (bit_and approx 15)
|
|
244
|
+
pos = pos + 3
|
|
245
|
+
|
|
246
|
+
def scanType:string "data"
|
|
247
|
+
if ((scanSs == 0) && (scanSe == 0)) {
|
|
248
|
+
if (scanAh == 0) {
|
|
249
|
+
scanType = "DC first"
|
|
250
|
+
} {
|
|
251
|
+
scanType = "DC refine"
|
|
252
|
+
}
|
|
253
|
+
} {
|
|
254
|
+
if (scanAh == 0) {
|
|
255
|
+
scanType = "AC first"
|
|
256
|
+
} {
|
|
257
|
+
scanType = "AC refine"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
; Print scan details with component info
|
|
262
|
+
def compList:string ""
|
|
263
|
+
def si 0
|
|
264
|
+
while (si < (array_length scanComponents)) {
|
|
265
|
+
if (si > 0) { compList = compList + "," }
|
|
266
|
+
compList = compList + (to_string (at scanComponents si))
|
|
267
|
+
si = si + 1
|
|
268
|
+
}
|
|
269
|
+
if (quiet == false) {
|
|
270
|
+
print (" Scan: comps=[" + compList + "] Ss=" + (to_string scanSs) + " Se=" + (to_string scanSe) + " Ah=" + (to_string scanAh) + " Al=" + (to_string scanAl) + " (" + scanType + ")")
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
; Find scan data end
|
|
274
|
+
def scanStart:int pos
|
|
275
|
+
def searchPos:int pos
|
|
276
|
+
while (searchPos < (dataLen - 1)) {
|
|
277
|
+
def b:int (buffer_get data searchPos)
|
|
278
|
+
if (b == 255) {
|
|
279
|
+
def nextB:int (buffer_get data (searchPos + 1))
|
|
280
|
+
if ((nextB != 0) && (nextB != 255)) {
|
|
281
|
+
if ((nextB >= 208) && (nextB <= 215)) {
|
|
282
|
+
searchPos = searchPos + 2
|
|
283
|
+
continue
|
|
284
|
+
}
|
|
285
|
+
break
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
searchPos = searchPos + 1
|
|
289
|
+
}
|
|
290
|
+
def scanLen:int (searchPos - scanStart)
|
|
291
|
+
|
|
292
|
+
def reader (new BitReader())
|
|
293
|
+
reader.init(data scanStart scanLen)
|
|
294
|
+
|
|
295
|
+
eobrun = 0
|
|
296
|
+
|
|
297
|
+
; Reset DC predictors for DC-first scans
|
|
298
|
+
if ((scanSs == 0) && (scanAh == 0)) {
|
|
299
|
+
def c 0
|
|
300
|
+
while (c < numComponents) {
|
|
301
|
+
def comp:JPEGComponent (at components c)
|
|
302
|
+
comp.prevDC = 0
|
|
303
|
+
c = c + 1
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (isProgressive) {
|
|
308
|
+
this.decodeProgressiveScan(reader scanComponents)
|
|
309
|
+
} {
|
|
310
|
+
this.decodeBaselineScan(reader scanComponents)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return searchPos
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
fn decodeProgressiveScan:void (reader:BitReader scanComps:[int]) {
|
|
317
|
+
def numScanComps:int (array_length scanComps)
|
|
318
|
+
|
|
319
|
+
def isDCFirst:boolean ((scanSs == 0) && (scanSe == 0) && (scanAh == 0))
|
|
320
|
+
def isDCRefine:boolean ((scanSs == 0) && (scanSe == 0) && (scanAh > 0))
|
|
321
|
+
def isACFirst:boolean ((scanSs > 0) && (scanAh == 0))
|
|
322
|
+
def isACRefine:boolean ((scanSs > 0) && (scanAh > 0))
|
|
323
|
+
|
|
324
|
+
if (numScanComps > 1) {
|
|
325
|
+
this.decodeInterleavedDC(reader scanComps isDCFirst isDCRefine)
|
|
326
|
+
} {
|
|
327
|
+
def compIdx:int (at scanComps 0)
|
|
328
|
+
if (isDCFirst) {
|
|
329
|
+
this.decodeDCFirst(reader compIdx)
|
|
330
|
+
}
|
|
331
|
+
if (isDCRefine) {
|
|
332
|
+
this.decodeDCRefine(reader compIdx)
|
|
333
|
+
}
|
|
334
|
+
if (isACFirst) {
|
|
335
|
+
this.decodeACFirst(reader compIdx)
|
|
336
|
+
}
|
|
337
|
+
if (isACRefine) {
|
|
338
|
+
this.decodeACRefine(reader compIdx)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
fn decodeInterleavedDC:void (reader:BitReader scanComps:[int] isDCFirst:boolean isDCRefine:boolean) {
|
|
344
|
+
def mcuY 0
|
|
345
|
+
while (mcuY < mcusPerCol) {
|
|
346
|
+
def mcuX 0
|
|
347
|
+
while (mcuX < mcusPerRow) {
|
|
348
|
+
def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
|
|
349
|
+
|
|
350
|
+
def sc 0
|
|
351
|
+
def numScanComps:int (array_length scanComps)
|
|
352
|
+
while (sc < numScanComps) {
|
|
353
|
+
def compIdx:int (at scanComps sc)
|
|
354
|
+
def comp:JPEGComponent (at components compIdx)
|
|
355
|
+
def buf:CoeffBuffer (at coeffBuffers compIdx)
|
|
356
|
+
|
|
357
|
+
def bv 0
|
|
358
|
+
while (bv < comp.vSamp) {
|
|
359
|
+
def bh 0
|
|
360
|
+
while (bh < comp.hSamp) {
|
|
361
|
+
def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
|
|
362
|
+
|
|
363
|
+
if (isDCFirst) {
|
|
364
|
+
def dcTable:HuffmanTable (huffman.getDCTable(comp.dcTableId))
|
|
365
|
+
def dcCategory:int (dcTable.decode(reader))
|
|
366
|
+
def dcDiff:int (reader.receiveExtend(dcCategory))
|
|
367
|
+
def dcValue:int (comp.prevDC + dcDiff)
|
|
368
|
+
comp.prevDC = dcValue
|
|
369
|
+
buf.setVal(blockIdx 0 (bit_shl dcValue scanAl))
|
|
370
|
+
}
|
|
371
|
+
if (isDCRefine) {
|
|
372
|
+
def bit:int (reader.readBit())
|
|
373
|
+
def oldVal:int (buf.get(blockIdx 0))
|
|
374
|
+
buf.setVal(blockIdx 0 (bit_or oldVal (bit_shl bit scanAl)))
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
bh = bh + 1
|
|
378
|
+
}
|
|
379
|
+
bv = bv + 1
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
sc = sc + 1
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
mcuX = mcuX + 1
|
|
386
|
+
}
|
|
387
|
+
mcuY = mcuY + 1
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
fn decodeDCFirst:void (reader:BitReader compIdx:int) {
|
|
392
|
+
def comp:JPEGComponent (at components compIdx)
|
|
393
|
+
def buf:CoeffBuffer (at coeffBuffers compIdx)
|
|
394
|
+
|
|
395
|
+
def dcTable:HuffmanTable (huffman.getDCTable(comp.dcTableId))
|
|
396
|
+
|
|
397
|
+
; Non-interleaved: iterate by MCU position to get correct block order
|
|
398
|
+
def mcuY 0
|
|
399
|
+
while (mcuY < mcusPerCol) {
|
|
400
|
+
def mcuX 0
|
|
401
|
+
while (mcuX < mcusPerRow) {
|
|
402
|
+
def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
|
|
403
|
+
|
|
404
|
+
def bv 0
|
|
405
|
+
while (bv < comp.vSamp) {
|
|
406
|
+
def bh 0
|
|
407
|
+
while (bh < comp.hSamp) {
|
|
408
|
+
def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
|
|
409
|
+
|
|
410
|
+
def dcCategory:int (dcTable.decode(reader))
|
|
411
|
+
def dcDiff:int (reader.receiveExtend(dcCategory))
|
|
412
|
+
def dcValue:int (comp.prevDC + dcDiff)
|
|
413
|
+
comp.prevDC = dcValue
|
|
414
|
+
|
|
415
|
+
buf.setVal(blockIdx 0 (bit_shl dcValue scanAl))
|
|
416
|
+
|
|
417
|
+
bh = bh + 1
|
|
418
|
+
}
|
|
419
|
+
bv = bv + 1
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
mcuX = mcuX + 1
|
|
423
|
+
}
|
|
424
|
+
mcuY = mcuY + 1
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
fn decodeDCRefine:void (reader:BitReader compIdx:int) {
|
|
429
|
+
def comp:JPEGComponent (at components compIdx)
|
|
430
|
+
def buf:CoeffBuffer (at coeffBuffers compIdx)
|
|
431
|
+
|
|
432
|
+
; Non-interleaved: iterate by MCU position
|
|
433
|
+
def mcuY 0
|
|
434
|
+
while (mcuY < mcusPerCol) {
|
|
435
|
+
def mcuX 0
|
|
436
|
+
while (mcuX < mcusPerRow) {
|
|
437
|
+
def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
|
|
438
|
+
|
|
439
|
+
def bv 0
|
|
440
|
+
while (bv < comp.vSamp) {
|
|
441
|
+
def bh 0
|
|
442
|
+
while (bh < comp.hSamp) {
|
|
443
|
+
def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
|
|
444
|
+
|
|
445
|
+
def bit:int (reader.readBit())
|
|
446
|
+
def oldVal:int (buf.get(blockIdx 0))
|
|
447
|
+
buf.setVal(blockIdx 0 (bit_or oldVal (bit_shl bit scanAl)))
|
|
448
|
+
|
|
449
|
+
bh = bh + 1
|
|
450
|
+
}
|
|
451
|
+
bv = bv + 1
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
mcuX = mcuX + 1
|
|
455
|
+
}
|
|
456
|
+
mcuY = mcuY + 1
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
fn decodeACFirst:void (reader:BitReader compIdx:int) {
|
|
461
|
+
def comp:JPEGComponent (at components compIdx)
|
|
462
|
+
def buf:CoeffBuffer (at coeffBuffers compIdx)
|
|
463
|
+
def acTable:HuffmanTable (huffman.getACTable(comp.acTableId))
|
|
464
|
+
|
|
465
|
+
; Non-interleaved: iterate by MCU position
|
|
466
|
+
def mcuY 0
|
|
467
|
+
while (mcuY < mcusPerCol) {
|
|
468
|
+
def mcuX 0
|
|
469
|
+
while (mcuX < mcusPerRow) {
|
|
470
|
+
def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
|
|
471
|
+
|
|
472
|
+
def bv 0
|
|
473
|
+
while (bv < comp.vSamp) {
|
|
474
|
+
def bh 0
|
|
475
|
+
while (bh < comp.hSamp) {
|
|
476
|
+
def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
|
|
477
|
+
|
|
478
|
+
if (eobrun > 0) {
|
|
479
|
+
eobrun = eobrun - 1
|
|
480
|
+
} {
|
|
481
|
+
def k:int scanSs
|
|
482
|
+
|
|
483
|
+
while (k <= scanSe) {
|
|
484
|
+
def symbol:int (acTable.decode(reader))
|
|
485
|
+
def run:int (bit_shr symbol 4)
|
|
486
|
+
def size:int (bit_and symbol 15)
|
|
487
|
+
|
|
488
|
+
if (size == 0) {
|
|
489
|
+
if (run == 15) {
|
|
490
|
+
k = k + 16
|
|
491
|
+
} {
|
|
492
|
+
if (run > 0) {
|
|
493
|
+
eobrun = (bit_shl 1 run)
|
|
494
|
+
eobrun = eobrun + (reader.readBits(run))
|
|
495
|
+
} {
|
|
496
|
+
eobrun = 1
|
|
497
|
+
}
|
|
498
|
+
eobrun = eobrun - 1
|
|
499
|
+
k = 64
|
|
500
|
+
}
|
|
501
|
+
} {
|
|
502
|
+
k = k + run
|
|
503
|
+
|
|
504
|
+
if (k <= scanSe) {
|
|
505
|
+
def acValue:int (reader.receiveExtend(size))
|
|
506
|
+
buf.setVal(blockIdx k (bit_shl acValue scanAl))
|
|
507
|
+
k = k + 1
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
bh = bh + 1
|
|
514
|
+
}
|
|
515
|
+
bv = bv + 1
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
mcuX = mcuX + 1
|
|
519
|
+
}
|
|
520
|
+
mcuY = mcuY + 1
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
fn decodeACRefine:void (reader:BitReader compIdx:int) {
|
|
525
|
+
def comp:JPEGComponent (at components compIdx)
|
|
526
|
+
def buf:CoeffBuffer (at coeffBuffers compIdx)
|
|
527
|
+
def acTable:HuffmanTable (huffman.getACTable(comp.acTableId))
|
|
528
|
+
|
|
529
|
+
; Non-interleaved: iterate by MCU position
|
|
530
|
+
def mcuY 0
|
|
531
|
+
while (mcuY < mcusPerCol) {
|
|
532
|
+
def mcuX 0
|
|
533
|
+
while (mcuX < mcusPerRow) {
|
|
534
|
+
def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
|
|
535
|
+
|
|
536
|
+
def bv 0
|
|
537
|
+
while (bv < comp.vSamp) {
|
|
538
|
+
def bh 0
|
|
539
|
+
while (bh < comp.hSamp) {
|
|
540
|
+
def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
|
|
541
|
+
|
|
542
|
+
this.decodeACRefineBlock(reader buf blockIdx acTable)
|
|
543
|
+
|
|
544
|
+
bh = bh + 1
|
|
545
|
+
}
|
|
546
|
+
bv = bv + 1
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
mcuX = mcuX + 1
|
|
550
|
+
}
|
|
551
|
+
mcuY = mcuY + 1
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
fn decodeACRefineBlock:void (reader:BitReader buf:CoeffBuffer blockIdx:int acTable:HuffmanTable) {
|
|
556
|
+
def k:int scanSs
|
|
557
|
+
|
|
558
|
+
if (eobrun > 0) {
|
|
559
|
+
while (k <= scanSe) {
|
|
560
|
+
def oldVal:int (buf.get(blockIdx k))
|
|
561
|
+
if (oldVal != 0) {
|
|
562
|
+
def bit:int (reader.readBit())
|
|
563
|
+
if (bit != 0) {
|
|
564
|
+
if (oldVal > 0) {
|
|
565
|
+
buf.setVal(blockIdx k (bit_or oldVal (bit_shl 1 scanAl)))
|
|
566
|
+
} {
|
|
567
|
+
buf.setVal(blockIdx k (oldVal - (bit_shl 1 scanAl)))
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
k = k + 1
|
|
572
|
+
}
|
|
573
|
+
eobrun = eobrun - 1
|
|
574
|
+
return
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
while (k <= scanSe) {
|
|
578
|
+
def symbol:int (acTable.decode(reader))
|
|
579
|
+
def run:int (bit_shr symbol 4)
|
|
580
|
+
def size:int (bit_and symbol 15)
|
|
581
|
+
|
|
582
|
+
if (size == 0) {
|
|
583
|
+
if (run == 15) {
|
|
584
|
+
def zerosToSkip:int 16
|
|
585
|
+
while ((zerosToSkip > 0) && (k <= scanSe)) {
|
|
586
|
+
def oldVal:int (buf.get(blockIdx k))
|
|
587
|
+
if (oldVal != 0) {
|
|
588
|
+
def bit:int (reader.readBit())
|
|
589
|
+
if (bit != 0) {
|
|
590
|
+
if (oldVal > 0) {
|
|
591
|
+
buf.setVal(blockIdx k (bit_or oldVal (bit_shl 1 scanAl)))
|
|
592
|
+
} {
|
|
593
|
+
buf.setVal(blockIdx k (oldVal - (bit_shl 1 scanAl)))
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
} {
|
|
597
|
+
zerosToSkip = zerosToSkip - 1
|
|
598
|
+
}
|
|
599
|
+
k = k + 1
|
|
600
|
+
}
|
|
601
|
+
} {
|
|
602
|
+
if (run > 0) {
|
|
603
|
+
eobrun = (bit_shl 1 run)
|
|
604
|
+
eobrun = eobrun + (reader.readBits(run))
|
|
605
|
+
} {
|
|
606
|
+
eobrun = 1
|
|
607
|
+
}
|
|
608
|
+
while (k <= scanSe) {
|
|
609
|
+
def oldVal:int (buf.get(blockIdx k))
|
|
610
|
+
if (oldVal != 0) {
|
|
611
|
+
def bit:int (reader.readBit())
|
|
612
|
+
if (bit != 0) {
|
|
613
|
+
if (oldVal > 0) {
|
|
614
|
+
buf.setVal(blockIdx k (bit_or oldVal (bit_shl 1 scanAl)))
|
|
615
|
+
} {
|
|
616
|
+
buf.setVal(blockIdx k (oldVal - (bit_shl 1 scanAl)))
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
k = k + 1
|
|
621
|
+
}
|
|
622
|
+
eobrun = eobrun - 1
|
|
623
|
+
}
|
|
624
|
+
} {
|
|
625
|
+
; size == 1: new non-zero coefficient after 'run' zeros
|
|
626
|
+
; First read the sign bit for the new coefficient
|
|
627
|
+
def signBit:int (reader.readBit())
|
|
628
|
+
def newCoeff:int (bit_shl 1 scanAl)
|
|
629
|
+
if (signBit == 0) {
|
|
630
|
+
newCoeff = (0 - newCoeff)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
def zerosToSkip:int run
|
|
634
|
+
while (k <= scanSe) {
|
|
635
|
+
def oldVal:int (buf.get(blockIdx k))
|
|
636
|
+
if (oldVal != 0) {
|
|
637
|
+
; Refine existing non-zero coefficient
|
|
638
|
+
def bit:int (reader.readBit())
|
|
639
|
+
if (bit != 0) {
|
|
640
|
+
if (oldVal > 0) {
|
|
641
|
+
buf.setVal(blockIdx k (bit_or oldVal (bit_shl 1 scanAl)))
|
|
642
|
+
} {
|
|
643
|
+
buf.setVal(blockIdx k (oldVal - (bit_shl 1 scanAl)))
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
} {
|
|
647
|
+
; Zero position
|
|
648
|
+
if (zerosToSkip > 0) {
|
|
649
|
+
zerosToSkip = zerosToSkip - 1
|
|
650
|
+
} {
|
|
651
|
+
; Found the position for new coefficient
|
|
652
|
+
buf.setVal(blockIdx k newCoeff)
|
|
653
|
+
k = k + 1
|
|
654
|
+
break
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
k = k + 1
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
fn decodeBaselineScan:void (reader:BitReader scanComps:[int]) {
|
|
664
|
+
def mcuY 0
|
|
665
|
+
while (mcuY < mcusPerCol) {
|
|
666
|
+
def mcuX 0
|
|
667
|
+
while (mcuX < mcusPerRow) {
|
|
668
|
+
def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
|
|
669
|
+
|
|
670
|
+
def sc 0
|
|
671
|
+
def numScanComps:int (array_length scanComps)
|
|
672
|
+
while (sc < numScanComps) {
|
|
673
|
+
def compIdx:int (at scanComps sc)
|
|
674
|
+
def comp:JPEGComponent (at components compIdx)
|
|
675
|
+
def quantTable:QuantizationTable (at quantTables comp.quantTableId)
|
|
676
|
+
def buf:CoeffBuffer (at coeffBuffers compIdx)
|
|
677
|
+
|
|
678
|
+
def bv 0
|
|
679
|
+
while (bv < comp.vSamp) {
|
|
680
|
+
def bh 0
|
|
681
|
+
while (bh < comp.hSamp) {
|
|
682
|
+
def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
|
|
683
|
+
|
|
684
|
+
; Decode DC
|
|
685
|
+
def dcTable:HuffmanTable (huffman.getDCTable(comp.dcTableId))
|
|
686
|
+
def dcCategory:int (dcTable.decode(reader))
|
|
687
|
+
def dcDiff:int (reader.receiveExtend(dcCategory))
|
|
688
|
+
def dcValue:int (comp.prevDC + dcDiff)
|
|
689
|
+
comp.prevDC = dcValue
|
|
690
|
+
|
|
691
|
+
def dcQuant:int (at quantTable.values 0)
|
|
692
|
+
buf.setVal(blockIdx 0 (dcValue * dcQuant))
|
|
693
|
+
|
|
694
|
+
; Decode AC
|
|
695
|
+
def acTable:HuffmanTable (huffman.getACTable(comp.acTableId))
|
|
696
|
+
def k 1
|
|
697
|
+
while (k < 64) {
|
|
698
|
+
def acSymbol:int (acTable.decode(reader))
|
|
699
|
+
|
|
700
|
+
if (acSymbol == 0) {
|
|
701
|
+
k = 64
|
|
702
|
+
} {
|
|
703
|
+
def run:int (bit_shr acSymbol 4)
|
|
704
|
+
def size:int (bit_and acSymbol 15)
|
|
705
|
+
|
|
706
|
+
if (acSymbol == 240) {
|
|
707
|
+
k = k + 16
|
|
708
|
+
} {
|
|
709
|
+
k = k + run
|
|
710
|
+
if (k < 64) {
|
|
711
|
+
def acValue:int (reader.receiveExtend(size))
|
|
712
|
+
def acQuant:int (at quantTable.values k)
|
|
713
|
+
buf.setVal(blockIdx k (acValue * acQuant))
|
|
714
|
+
k = k + 1
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
bh = bh + 1
|
|
721
|
+
}
|
|
722
|
+
bv = bv + 1
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
sc = sc + 1
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
mcuX = mcuX + 1
|
|
729
|
+
}
|
|
730
|
+
mcuY = mcuY + 1
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
fn parseMarkers:boolean () {
|
|
735
|
+
def pos 0
|
|
736
|
+
|
|
737
|
+
if (dataLen < 2) {
|
|
738
|
+
if (quiet == false) {
|
|
739
|
+
print "Error: File too small"
|
|
740
|
+
}
|
|
741
|
+
return false
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
def m1:int (buffer_get data 0)
|
|
745
|
+
def m2:int (buffer_get data 1)
|
|
746
|
+
if ((m1 != 255) || (m2 != 216)) {
|
|
747
|
+
if (quiet == false) {
|
|
748
|
+
print "Error: Not a JPEG file"
|
|
749
|
+
}
|
|
750
|
+
return false
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
pos = 2
|
|
754
|
+
if (quiet == false) {
|
|
755
|
+
print "Parsing JPEG markers..."
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
while (pos < (dataLen - 1)) {
|
|
759
|
+
def marker1:int (buffer_get data pos)
|
|
760
|
+
if (marker1 != 255) {
|
|
761
|
+
pos = pos + 1
|
|
762
|
+
continue
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
def marker2:int (buffer_get data (pos + 1))
|
|
766
|
+
|
|
767
|
+
if (marker2 == 255) {
|
|
768
|
+
pos = pos + 1
|
|
769
|
+
continue
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
if (marker2 == 0) {
|
|
773
|
+
pos = pos + 2
|
|
774
|
+
continue
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if (marker2 == 216) {
|
|
778
|
+
pos = pos + 2
|
|
779
|
+
continue
|
|
780
|
+
}
|
|
781
|
+
if (marker2 == 217) {
|
|
782
|
+
if (quiet == false) {
|
|
783
|
+
print " End of Image"
|
|
784
|
+
}
|
|
785
|
+
return true
|
|
786
|
+
}
|
|
787
|
+
if ((marker2 >= 208) && (marker2 <= 215)) {
|
|
788
|
+
pos = pos + 2
|
|
789
|
+
continue
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
if ((pos + 4) > dataLen) {
|
|
793
|
+
return true
|
|
794
|
+
}
|
|
795
|
+
def markerLen:int (this.readUint16BE(pos + 2))
|
|
796
|
+
def dataStart:int (pos + 4)
|
|
797
|
+
def markerDataLen:int (markerLen - 2)
|
|
798
|
+
|
|
799
|
+
if (marker2 == 192) {
|
|
800
|
+
if (quiet == false) {
|
|
801
|
+
print " SOF0 (Baseline DCT)"
|
|
802
|
+
}
|
|
803
|
+
this.parseSOF(dataStart markerDataLen 0)
|
|
804
|
+
}
|
|
805
|
+
if (marker2 == 193) {
|
|
806
|
+
if (quiet == false) {
|
|
807
|
+
print " SOF1 (Extended Sequential)"
|
|
808
|
+
}
|
|
809
|
+
this.parseSOF(dataStart markerDataLen 1)
|
|
810
|
+
}
|
|
811
|
+
if (marker2 == 194) {
|
|
812
|
+
if (quiet == false) {
|
|
813
|
+
print " SOF2 (Progressive DCT)"
|
|
814
|
+
}
|
|
815
|
+
this.parseSOF(dataStart markerDataLen 2)
|
|
816
|
+
}
|
|
817
|
+
if (marker2 == 196) {
|
|
818
|
+
if (quiet == false) {
|
|
819
|
+
print " DHT (Huffman Tables)"
|
|
820
|
+
}
|
|
821
|
+
huffman.parseDHT(data dataStart markerDataLen)
|
|
822
|
+
}
|
|
823
|
+
if (marker2 == 219) {
|
|
824
|
+
if (quiet == false) {
|
|
825
|
+
print " DQT (Quantization Tables)"
|
|
826
|
+
}
|
|
827
|
+
this.parseDQT(dataStart markerDataLen)
|
|
828
|
+
}
|
|
829
|
+
if (marker2 == 218) {
|
|
830
|
+
if (quiet == false) {
|
|
831
|
+
print " SOS (Start of Scan)"
|
|
832
|
+
}
|
|
833
|
+
def nextPos:int (this.parseSOS(dataStart markerDataLen))
|
|
834
|
+
pos = nextPos
|
|
835
|
+
continue
|
|
836
|
+
}
|
|
837
|
+
if (marker2 == 224) {
|
|
838
|
+
if (quiet == false) {
|
|
839
|
+
print " APP0 (JFIF)"
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
if (marker2 == 225) {
|
|
843
|
+
if (quiet == false) {
|
|
844
|
+
print " APP1 (EXIF)"
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
pos = pos + 2 + markerLen
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
return true
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
fn dequantizeCoefficients:void () {
|
|
855
|
+
def c 0
|
|
856
|
+
while (c < numComponents) {
|
|
857
|
+
def comp:JPEGComponent (at components c)
|
|
858
|
+
def quantTable:QuantizationTable (at quantTables comp.quantTableId)
|
|
859
|
+
def buf:CoeffBuffer (at coeffBuffers c)
|
|
860
|
+
|
|
861
|
+
def blockIdx 0
|
|
862
|
+
while (blockIdx < buf.numBlocks) {
|
|
863
|
+
def k 0
|
|
864
|
+
while (k < 64) {
|
|
865
|
+
def oldVal:int (buf.get(blockIdx k))
|
|
866
|
+
def quantVal:int (at quantTable.values k)
|
|
867
|
+
buf.setVal(blockIdx k (oldVal * quantVal))
|
|
868
|
+
k = k + 1
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
blockIdx = blockIdx + 1
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
c = c + 1
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
fn buildImage:ImageBuffer () {
|
|
879
|
+
if (isProgressive) {
|
|
880
|
+
if (quiet == false) {
|
|
881
|
+
print "Dequantizing coefficients..."
|
|
882
|
+
}
|
|
883
|
+
this.dequantizeCoefficients()
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
def img (new ImageBuffer())
|
|
887
|
+
img.init(width height)
|
|
888
|
+
|
|
889
|
+
if (quiet == false) {
|
|
890
|
+
print "Building image..."
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
def mcuY 0
|
|
894
|
+
while (mcuY < mcusPerCol) {
|
|
895
|
+
def mcuX 0
|
|
896
|
+
while (mcuX < mcusPerRow) {
|
|
897
|
+
def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
|
|
898
|
+
def baseX:int (mcuX * mcuWidth)
|
|
899
|
+
def baseY:int (mcuY * mcuHeight)
|
|
900
|
+
|
|
901
|
+
def comp0:JPEGComponent (at components 0)
|
|
902
|
+
def yBuf:CoeffBuffer (at coeffBuffers 0)
|
|
903
|
+
|
|
904
|
+
; IDCT for Y blocks
|
|
905
|
+
def yBlocksData:[int]
|
|
906
|
+
def bv 0
|
|
907
|
+
while (bv < comp0.vSamp) {
|
|
908
|
+
def bh 0
|
|
909
|
+
while (bh < comp0.hSamp) {
|
|
910
|
+
def blockIdx:int (mcuIdx * comp0.hSamp * comp0.vSamp + bv * comp0.hSamp + bh)
|
|
911
|
+
|
|
912
|
+
def blockCoeffs:int_buffer (int_buffer_alloc 64)
|
|
913
|
+
def k 0
|
|
914
|
+
while (k < 64) {
|
|
915
|
+
int_buffer_set blockCoeffs k (yBuf.get(blockIdx k))
|
|
916
|
+
k = k + 1
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
def tempBlock:int_buffer (idct.dezigzag(blockCoeffs))
|
|
920
|
+
|
|
921
|
+
def blockPixels:int_buffer (int_buffer_alloc 64)
|
|
922
|
+
int_buffer_fill blockPixels 0 0 64
|
|
923
|
+
idct.transform(tempBlock blockPixels)
|
|
924
|
+
|
|
925
|
+
k = 0
|
|
926
|
+
while (k < 64) {
|
|
927
|
+
push yBlocksData (int_buffer_get blockPixels k)
|
|
928
|
+
k = k + 1
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
bh = bh + 1
|
|
932
|
+
}
|
|
933
|
+
bv = bv + 1
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
; Cb/Cr blocks
|
|
937
|
+
def cbBlock:[int]
|
|
938
|
+
def crBlock:[int]
|
|
939
|
+
|
|
940
|
+
if (numComponents >= 3) {
|
|
941
|
+
; Cb
|
|
942
|
+
def cbBuf:CoeffBuffer (at coeffBuffers 1)
|
|
943
|
+
def cbBlockIdx:int (mcuIdx)
|
|
944
|
+
|
|
945
|
+
def blockCoeffs:int_buffer (int_buffer_alloc 64)
|
|
946
|
+
def k 0
|
|
947
|
+
while (k < 64) {
|
|
948
|
+
int_buffer_set blockCoeffs k (cbBuf.get(cbBlockIdx k))
|
|
949
|
+
k = k + 1
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
def tempBlock:int_buffer (idct.dezigzag(blockCoeffs))
|
|
953
|
+
def cbPixels:int_buffer (int_buffer_alloc 64)
|
|
954
|
+
int_buffer_fill cbPixels 0 0 64
|
|
955
|
+
idct.transform(tempBlock cbPixels)
|
|
956
|
+
k = 0
|
|
957
|
+
while (k < 64) {
|
|
958
|
+
push cbBlock (int_buffer_get cbPixels k)
|
|
959
|
+
k = k + 1
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
; Cr
|
|
963
|
+
def crBuf:CoeffBuffer (at coeffBuffers 2)
|
|
964
|
+
def crBlockIdx:int (mcuIdx)
|
|
965
|
+
|
|
966
|
+
def crCoeffs:int_buffer (int_buffer_alloc 64)
|
|
967
|
+
k = 0
|
|
968
|
+
while (k < 64) {
|
|
969
|
+
int_buffer_set crCoeffs k (crBuf.get(crBlockIdx k))
|
|
970
|
+
k = k + 1
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
def crTempBlock:int_buffer (idct.dezigzag(crCoeffs))
|
|
974
|
+
def crPixels:int_buffer (int_buffer_alloc 64)
|
|
975
|
+
int_buffer_fill crPixels 0 0 64
|
|
976
|
+
idct.transform(crTempBlock crPixels)
|
|
977
|
+
k = 0
|
|
978
|
+
while (k < 64) {
|
|
979
|
+
push crBlock (int_buffer_get crPixels k)
|
|
980
|
+
k = k + 1
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
this.writeMCU(img baseX baseY yBlocksData cbBlock crBlock)
|
|
985
|
+
|
|
986
|
+
mcuX = mcuX + 1
|
|
987
|
+
}
|
|
988
|
+
mcuY = mcuY + 1
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
return img
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
fn writeMCU:void (img:ImageBuffer baseX:int baseY:int yBlocksData:[int] cbBlock:[int] crBlock:[int]) {
|
|
995
|
+
def comp0:JPEGComponent (at components 0)
|
|
996
|
+
|
|
997
|
+
if ((maxHSamp == 1) && (maxVSamp == 1)) {
|
|
998
|
+
def py 0
|
|
999
|
+
while (py < 8) {
|
|
1000
|
+
def px 0
|
|
1001
|
+
while (px < 8) {
|
|
1002
|
+
def imgX:int (baseX + px)
|
|
1003
|
+
def imgY:int (baseY + py)
|
|
1004
|
+
|
|
1005
|
+
if ((imgX < width) && (imgY < height)) {
|
|
1006
|
+
def idx:int ((py * 8) + px)
|
|
1007
|
+
def y:int (at yBlocksData idx)
|
|
1008
|
+
|
|
1009
|
+
def cb:int 128
|
|
1010
|
+
def cr:int 128
|
|
1011
|
+
if (numComponents >= 3) {
|
|
1012
|
+
cb = (at cbBlock idx)
|
|
1013
|
+
cr = (at crBlock idx)
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
def r:int (y + (bit_shr (359 * (cr - 128)) 8))
|
|
1017
|
+
def g:int (y - (bit_shr (88 * (cb - 128)) 8) - (bit_shr (183 * (cr - 128)) 8))
|
|
1018
|
+
def b:int (y + (bit_shr (454 * (cb - 128)) 8))
|
|
1019
|
+
|
|
1020
|
+
if (r < 0) { r = 0 }
|
|
1021
|
+
if (r > 255) { r = 255 }
|
|
1022
|
+
if (g < 0) { g = 0 }
|
|
1023
|
+
if (g > 255) { g = 255 }
|
|
1024
|
+
if (b < 0) { b = 0 }
|
|
1025
|
+
if (b > 255) { b = 255 }
|
|
1026
|
+
|
|
1027
|
+
img.setPixelRGB(imgX imgY r g b)
|
|
1028
|
+
}
|
|
1029
|
+
px = px + 1
|
|
1030
|
+
}
|
|
1031
|
+
py = py + 1
|
|
1032
|
+
}
|
|
1033
|
+
return
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
if ((maxHSamp == 2) && (maxVSamp == 2)) {
|
|
1037
|
+
def blockIdx 0
|
|
1038
|
+
def blockY 0
|
|
1039
|
+
while (blockY < 2) {
|
|
1040
|
+
def blockX 0
|
|
1041
|
+
while (blockX < 2) {
|
|
1042
|
+
def yBlockOffset:int (blockIdx * 64)
|
|
1043
|
+
|
|
1044
|
+
def py 0
|
|
1045
|
+
while (py < 8) {
|
|
1046
|
+
def px 0
|
|
1047
|
+
while (px < 8) {
|
|
1048
|
+
def imgX:int (baseX + (blockX * 8) + px)
|
|
1049
|
+
def imgY:int (baseY + (blockY * 8) + py)
|
|
1050
|
+
|
|
1051
|
+
if ((imgX < width) && (imgY < height)) {
|
|
1052
|
+
def yIdx:int (yBlockOffset + (py * 8) + px)
|
|
1053
|
+
def y:int (at yBlocksData yIdx)
|
|
1054
|
+
|
|
1055
|
+
def chromaX:int ((blockX * 4) + (bit_shr px 1))
|
|
1056
|
+
def chromaY:int ((blockY * 4) + (bit_shr py 1))
|
|
1057
|
+
def chromaIdx:int ((chromaY * 8) + chromaX)
|
|
1058
|
+
|
|
1059
|
+
def cb:int 128
|
|
1060
|
+
def cr:int 128
|
|
1061
|
+
if (numComponents >= 3) {
|
|
1062
|
+
cb = (at cbBlock chromaIdx)
|
|
1063
|
+
cr = (at crBlock chromaIdx)
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
def r:int (y + (bit_shr (359 * (cr - 128)) 8))
|
|
1067
|
+
def g:int (y - (bit_shr (88 * (cb - 128)) 8) - (bit_shr (183 * (cr - 128)) 8))
|
|
1068
|
+
def b:int (y + (bit_shr (454 * (cb - 128)) 8))
|
|
1069
|
+
|
|
1070
|
+
if (r < 0) { r = 0 }
|
|
1071
|
+
if (r > 255) { r = 255 }
|
|
1072
|
+
if (g < 0) { g = 0 }
|
|
1073
|
+
if (g > 255) { g = 255 }
|
|
1074
|
+
if (b < 0) { b = 0 }
|
|
1075
|
+
if (b > 255) { b = 255 }
|
|
1076
|
+
|
|
1077
|
+
img.setPixelRGB(imgX imgY r g b)
|
|
1078
|
+
}
|
|
1079
|
+
px = px + 1
|
|
1080
|
+
}
|
|
1081
|
+
py = py + 1
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
blockIdx = blockIdx + 1
|
|
1085
|
+
blockX = blockX + 1
|
|
1086
|
+
}
|
|
1087
|
+
blockY = blockY + 1
|
|
1088
|
+
}
|
|
1089
|
+
return
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
; Fallback grayscale
|
|
1093
|
+
def yLen:int (array_length yBlocksData)
|
|
1094
|
+
if (yLen > 0) {
|
|
1095
|
+
def py 0
|
|
1096
|
+
while (py < 8) {
|
|
1097
|
+
def px 0
|
|
1098
|
+
while (px < 8) {
|
|
1099
|
+
def imgX:int (baseX + px)
|
|
1100
|
+
def imgY:int (baseY + py)
|
|
1101
|
+
if ((imgX < width) && (imgY < height)) {
|
|
1102
|
+
def y:int (at yBlocksData ((py * 8) + px))
|
|
1103
|
+
img.setPixelRGB(imgX imgY y y y)
|
|
1104
|
+
}
|
|
1105
|
+
px = px + 1
|
|
1106
|
+
}
|
|
1107
|
+
py = py + 1
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
fn decode:ImageBuffer (dirPath:string fileName:string) {
|
|
1113
|
+
def bytes:buffer (buffer_read_file dirPath fileName)
|
|
1114
|
+
if (quiet == false) {
|
|
1115
|
+
print ("Decoding JPEG: " + fileName + " (" + (to_string (buffer_length bytes)) + " bytes)")
|
|
1116
|
+
}
|
|
1117
|
+
return (this.decodeBytes(bytes))
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
; The same decode, from bytes already in hand. `EVGImageDecode` sniffs the
|
|
1121
|
+
; markers and dispatches, and it has bytes, not a path — without this it
|
|
1122
|
+
; could reach the baseline decoder and not this one, so a progressive JPEG
|
|
1123
|
+
; in a document was "some of the photos are simply missing".
|
|
1124
|
+
fn decodeBytes:ImageBuffer (bytes:buffer) {
|
|
1125
|
+
data = bytes
|
|
1126
|
+
dataLen = (buffer_length data)
|
|
1127
|
+
|
|
1128
|
+
def ok:boolean (this.parseMarkers())
|
|
1129
|
+
if (ok == false) {
|
|
1130
|
+
if (quiet == false) {
|
|
1131
|
+
print "Error parsing JPEG markers"
|
|
1132
|
+
}
|
|
1133
|
+
def errImg (new ImageBuffer())
|
|
1134
|
+
errImg.init(1 1)
|
|
1135
|
+
return errImg
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
if ((width == 0) || (height == 0)) {
|
|
1139
|
+
if (quiet == false) {
|
|
1140
|
+
print "Error: Invalid image dimensions"
|
|
1141
|
+
}
|
|
1142
|
+
def errImg (new ImageBuffer())
|
|
1143
|
+
errImg.init(1 1)
|
|
1144
|
+
return errImg
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
def img:ImageBuffer (this.buildImage())
|
|
1148
|
+
|
|
1149
|
+
if (quiet == false) {
|
|
1150
|
+
print "Decode complete!"
|
|
1151
|
+
}
|
|
1152
|
+
return img
|
|
1153
|
+
}
|
|
1154
|
+
}
|