Victor Ostromoukhov

62 papers A* 7Journal 32Unranked 22
YearRankTypeTitle / Venue / Authors
2025 J jnl
CoRR
Abdalla G. M. Ahmed, Matt Pharr, Victor Ostromoukhov, Hui Huang
2025 J jnl
ACM Trans. Graph.
Abdalla G. M. Ahmed, Matt Pharr, Victor Ostromoukhov, Hui Huang
2025 J jnl
ACM Trans. Graph.
Nicolas Bonneel, David Coeurjolly, Jean-Claude Iehl, Victor Ostromoukhov
2024 J jnl
ACM Trans. Graph.
Bastien Doignies, David Coeurjolly, Nicolas Bonneel, Julie Digne, Jean-Claude Iehl, Victor Ostromoukhov
2024 conf
SIGGRAPH (Conference Paper Track)
Victor Ostromoukhov, Nicolas Bonneel, David Coeurjolly, Jean-Claude Iehl
2023 A* conf
SIGGRAPH Asia
Bastien Doignies, Nicolas Bonneel, David Coeurjolly, Julie Digne, Loïs Paulin, Jean-Claude Iehl, Victor Ostromoukhov
2023 J jnl
CoRR
Bastien Doignies, Nicolas Bonneel, David Coeurjolly, Julie Digne, Loïs Paulin, Jean-Claude Iehl, Victor Ostromoukhov
2023 J jnl
CoRR
Loïs Paulin, David Coeurjolly, Nicolas Bonneel, Jean-Claude Iehl, Victor Ostromoukhov, Alexander Keller
2022 J jnl
ACM Trans. Graph.
Loïs Paulin, Nicolas Bonneel, David Coeurjolly, Jean-Claude Iehl, Alexander Keller, Victor Ostromoukhov
2021 J jnl
ACM Trans. Graph.
Loïs Paulin, David Coeurjolly, Jean-Claude Iehl, Nicolas Bonneel, Alexander Keller, Victor Ostromoukhov
2020 J jnl
Comput. Graph. Forum
Gurprit Singh, Kartic Subr, David Coeurjolly, Victor Ostromoukhov, Wojciech Jarosz
2020 J jnl
ACM Trans. Graph.
Loïs Paulin, Nicolas Bonneel, David Coeurjolly, Jean-Claude Iehl, Antoine Webanck, Mathieu Desbrun, Victor Ostromoukhov
2019 conf
SIGGRAPH Talks
Eric Heitz, Laurent Belcour, Victor Ostromoukhov, David Coeurjolly, Jean-Claude Iehl
2019 J jnl
Comput. Graph. Forum
Gurprit Singh, Cengiz Öztireli, Abdalla G. M. Ahmed, David Coeurjolly, Kartic Subr, Oliver Deussen, Victor Ostromoukhov, Ravi Ramamoorthi, Wojciech Jarosz
2019 J jnl
CoRR
Matteo P. Lanaro, Hélène Perrier, David Coeurjolly, Victor Ostromoukhov, Alessandro Rizzi
2018 J jnl
J. Math. Imaging Vis.
Kacper Pluta, Tristan Roussillon, David Coeurjolly, Pascal Romon, Yukiko Kenmochi, Victor Ostromoukhov
2018 J jnl
Comput. Graph. Forum
Hélène Perrier, David Coeurjolly, Feng Xie, Matt Pharr, Pat Hanrahan, Victor Ostromoukhov
2016 J jnl
ACM Trans. Graph.
Abdalla G. M. Ahmed, Hélène Perrier, David Coeurjolly, Victor Ostromoukhov, Jianwei Guo, Dong-Ming Yan, Hui Huang, Oliver Deussen
2015 J jnl
Vis. Comput.
Frederic Cordier, Nadia Magnenat-Thalmann, Victor Ostromoukhov, Hyewon Seo
2015 J jnl
Comput. Graph. Forum
Jonathan Dupuy, Eric Heitz, Jean-Claude Iehl, Pierre Poulin, Victor Ostromoukhov
2015 J jnl
CoRR
Michael Kazhdan, Gurprit Singh, Adrien Pilleboue, David Coeurjolly, Victor Ostromoukhov
2015 J jnl
ACM Trans. Graph.
Adrien Pilleboue, Gurprit Singh, David Coeurjolly, Michael Kazhdan, Victor Ostromoukhov
2014 J jnl
ACM Trans. Graph.
Florent Wachtel, Adrien Pilleboue, David Coeurjolly, Katherine Breeden, Gurprit Singh, Gaël Cathelin, Fernando de Goes, Mathieu Desbrun, Victor Ostromoukhov
2014 J jnl
Multim. Tools Appl.
Sanghyun Seo, Victor Ostromoukhov
2013 J jnl
Multim. Tools Appl.
Sanghyun Seo, Youngsup Park, Victor Ostromoukhov
2013 conf
SIGGRAPH ASIA Technical Briefs
Guillaume Bouchard, Jean-Claude Iehl, Victor Ostromoukhov, Pierre Poulin
2013 J jnl
ACM Trans. Graph.
Jonathan Dupuy, Eric Heitz, Jean-Claude Iehl, Pierre Poulin, Fabrice Neyret, Victor Ostromoukhov
2013 ch.
Image and Video-Based Artistic Stylisation
Victor Ostromoukhov
2012 J jnl
ACM Trans. Graph.
Fernando de Goes, Katherine Breeden, Victor Ostromoukhov, Mathieu Desbrun
2012 J jnl
Comput. Aided Geom. Des.
Vincent Nivoliers, Cédric Gérot, Victor Ostromoukhov, Neil F. Stewart
2009 J jnl
ACM Trans. Graph.
Jianghao Chang, Benoît Alain, Victor Ostromoukhov
2008 J jnl
Vis. Comput.
Fabrice Rousselle, Petrik Clarberg, Luc Leblanc, Victor Ostromoukhov, Pierre Poulin
2008 J jnl
CoRR
David Vanderhaeghe, Victor Ostromoukhov
2008 conf
SIGGRAPH Classes
Ares Lagae, Craig S. Kaplan, Chi-Wing Fu, Victor Ostromoukhov, Oliver Deussen
2007 conf
NPAR
Simon Bouvier-Zappa, Victor Ostromoukhov, Pierre Poulin
2007 J jnl
ACM Trans. Graph.
Victor Ostromoukhov
2004 J jnl
ACM Trans. Graph.
Victor Ostromoukhov, Charles Donohue, Pierre-Marc Jodoin
2003 conf
Color Imaging: Processing, Hardcopy, and Applications
Pierre-Marc Jodoin, Victor Ostromoukhov
2002 conf
Color Imaging: Device-Independent Color, Color Hardcopy, and Applications
Pierre-Marc Jodoin, Victor Ostromoukhov
2002 conf
NPAR
Pierre-Marc Jodoin, Emric Epstein, Martin Granger-Piché, Victor Ostromoukhov
2001 A* conf
SIGGRAPH
Victor Ostromoukhov
2001 conf
Rendering Techniques
Frédo Durand, Victor Ostromoukhov, Mathieu Miller, François Duranleau, Julie Dorsey
2001 conf
Color Imaging: Device-Independent Color, Color Hardcopy, and Graphic Arts
Victor Ostromoukhov
2000 conf
Color Imaging: Device-Independent Color, Color Hardcopy, and Graphic Arts
Victor Ostromoukhov
1999 A* conf
SIGGRAPH
Victor Ostromoukhov
1999 A* conf
SIGGRAPH
Victor Ostromoukhov, Roger D. Hersch
1999 conf
Color Imaging: Device-Independent Color, Color Hardcopy, and Graphic Arts
Victor Ostromoukhov, Roger D. Hersch
1999 J jnl
J. Electronic Imaging
Victor Ostromoukhov, Roger D. Hersch
1998 conf
EP
Nicolas Rudaz, Roger D. Hersch, Victor Ostromoukhov
1998 conf
EP
Victor Ostromoukhov
1998 A* conf
SIGGRAPH
Eric J. Stollnitz, Victor Ostromoukhov, David Salesin
1998 conf
Electronic Imaging
Victor Ostromoukhov, Roger D. Hersch
1997 conf
CIC
Nicolas Rudaz, Roger D. Hersch, Victor Ostromoukhov
1996 conf
ICIP (1)
Victor Ostromoukhov, Patrick Emmel, Nicolas Rudaz, Isaac Amidror, Roger D. Hersch
1996 conf
CIC
Patrick Emmel, Isaac Amidror, Victor Ostromoukhov, Roger D. Hersch
1995 conf
CIC
Patrick Emmel, Roger D. Hersch, Victor Ostromoukhov
1995 A* conf
SIGGRAPH
Victor Ostromoukhov, Roger D. Hersch
1994 A* conf
SIGGRAPH
Victor Ostromoukhov, Roger D. Hersch, Isaac Amidror
1994 J jnl
J. Electronic Imaging
Isaac Amidror, Roger D. Hersch, Victor Ostromoukhov
1994 conf
Device-Independent Color Imaging
Victor Ostromoukhov, Roger D. Hersch, Cécile Péraire, Isaac Amidror, Patrick Emmel
1993 conf
Device-Independent Color Imaging and Imaging Systems Integration
Victor Ostromoukhov
1993 conf
ICCG
Victor Ostromoukhov
tests/unit/test_smali_normalization.py
← Index tests/unit/test_smali_normalization.py python
"""Unit tests for smali semantic normalization.

Tests the three normalization levels (category, opcode, opcode_api),
opcode categorization, ACFG feature index mapping, and integration
with MinHash computation.
"""
import pytest

pytestmark = [pytest.mark.unit, pytest.mark.apk, pytest.mark.decompile]


class TestCategorizeOpcode:
    """Tests for opcode -> semantic category mapping."""

    def test_arithmetic(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("add-int") == "ALU"
        assert categorize_opcode("mul-long/2addr") == "ALU"
        assert categorize_opcode("neg-int") == "ALU"

    def test_data_movement(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("move-result") == "MOV"
        assert categorize_opcode("const/4") == "CONST"
        assert categorize_opcode("const-string") == "CONST"

    def test_memory_access(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("iget-object") == "LOAD"
        assert categorize_opcode("sput-wide") == "STORE"
        assert categorize_opcode("aget-byte") == "LOAD"

    def test_invocation(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("invoke-virtual") == "CALL"
        assert categorize_opcode("invoke-static") == "CALL"
        assert categorize_opcode("invoke-direct") == "CALL"

    def test_control_flow(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("if-eqz") == "BRANCH"
        assert categorize_opcode("goto") == "JMP"
        assert categorize_opcode("goto/16") == "JMP"
        assert categorize_opcode("return-void") == "RET"

    def test_comparison(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("cmp-long") == "CMP"
        assert categorize_opcode("cmpl-float") == "CMP"
        assert categorize_opcode("cmpg-double") == "CMP"

    def test_conversion(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("int-to-long") == "CONV"
        assert categorize_opcode("float-to-int") == "CONV"

    def test_object_type(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("new-instance") == "ALLOC"
        assert categorize_opcode("check-cast") == "TYPE"
        assert categorize_opcode("instance-of") == "TYPE"

    def test_exception_sync(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("throw") == "EXC"
        assert categorize_opcode("monitor-enter") == "SYNC"

    def test_unknown(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("nop") == "OTHER"


class TestNormalizeInstruction:
    """Tests for single instruction normalization at various levels."""

    def test_category_level(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        assert normalize_instruction("add-int v0, v1, v2", "category") == "ALU"
        assert normalize_instruction("invoke-virtual {p0}, Lcom/Foo;->bar()V", "category") == "CALL"
        assert normalize_instruction("return-void", "category") == "RET"

    def test_opcode_level_strips_width(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # Width variants collapse to same base
        assert normalize_instruction("add-int v0, v1, v2", "opcode") == "add"
        assert normalize_instruction("add-long v0, v2, v4", "opcode") == "add"
        assert normalize_instruction("add-float v0, v1, v2", "opcode") == "add"
        # Addressing modes collapse too
        assert normalize_instruction("add-int/2addr v0, v1", "opcode") == "add"

    def test_opcode_api_invoke(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "invoke-virtual {p0, v0}, Lcom/example/Foo;->bar(I)V"
        )
        assert result == "CALL Lcom/example/Foo;->bar(I)V"

    def test_opcode_api_invoke_no_ref(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # If somehow no method ref is found, fallback to CALL
        assert normalize_instruction("invoke-virtual {v0}") == "CALL"

    def test_opcode_api_field_load(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iget-object v0, p0, Lcom/Foo;->mField:Ljava/lang/String;"
        )
        assert result == "LOAD Lcom/Foo;->mField:Ljava/lang/String;"

    def test_opcode_api_field_store(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iput-object v0, p0, Lcom/Foo;->mField:Ljava/lang/String;"
        )
        assert result == "STORE Lcom/Foo;->mField:Ljava/lang/String;"

    def test_opcode_api_androguard_field_format(self):
        """androguard uses space instead of colon in field references."""
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iget-object v0, p0, Lcom/Foo;->mField Ljava/lang/String;"
        )
        assert result.startswith("LOAD")
        assert "Lcom/Foo;->mField" in result

    def test_opcode_api_new_instance(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "new-instance v0, Lcom/example/MyClass;"
        )
        assert result == "ALLOC Lcom/example/MyClass;"

    def test_opcode_api_const_string(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            'const-string v0, "hello world"'
        )
        assert result == 'CONST_STR "hello world"'

    def test_opcode_api_const_string_jumbo(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            'const-string/jumbo v0, "large string"'
        )
        assert result == 'CONST_STR "large string"'

    def test_opcode_api_fallback_to_category(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # Non-special instructions fall back to category
        assert normalize_instruction("add-int v0, v1, v2") == "ALU"
        assert normalize_instruction("return-void") == "RET"
        assert normalize_instruction("nop") == "OTHER"

    def test_empty_input(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        assert normalize_instruction("") == ""
        assert normalize_instruction("   ") == ""


class TestNormalizeMethodBody:
    """Tests for full method body normalization."""

    def test_filters_directives_labels_comments(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        body = """\
.locals 2
# comment
:label_0
add-int v0, v1, v2
.line 42
invoke-virtual {p0}, Lcom/Foo;->bar()V
return-void
"""
        result = normalize_method_body(body, "category")
        assert result == ["ALU", "CALL", "RET"]

    def test_opcode_api_preserves_api_refs(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        body = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->setX(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
return-void
"""
        result = normalize_method_body(body, "opcode_api")
        assert result[0] == "CONST"
        assert result[1] == "CALL Lcom/Foo;->setX(I)V"
        assert result[2] == "LOAD Lcom/Foo;->name:Ljava/lang/String;"
        assert result[3] == "RET"

    def test_empty_body(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        assert normalize_method_body("") == []
        assert normalize_method_body("\n\n") == []


class TestNormalizationWithMinHash:
    """Integration tests: normalization + MinHash computation."""

    def test_minhash_returns_signature(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
add-int v2, v0, v1
return-void
"""
        sig = compute_minhash(body)
        assert sig is not None
        assert len(sig) == 64
        assert all(0 <= v < 256 for v in sig)

    def test_minhash_register_invariance(self):
        """Same operations with different registers should produce identical signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_a = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
add-int v2, v0, v1
return-void
"""
        body_b = """\
const/4 v3, 0x0
invoke-virtual {p1, v3}, Lcom/Foo;->bar(I)V
iget-object v4, p1, Lcom/Foo;->name:Ljava/lang/String;
add-int v5, v3, v4
return-void
"""
        sig_a = compute_minhash(body_a)
        sig_b = compute_minhash(body_b)
        assert sig_a == sig_b

    def test_minhash_width_invariance(self):
        """Width variants of same operations should produce identical signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_int = """\
add-int v0, v1, v2
sub-int v3, v0, v1
mul-int v4, v0, v3
return v4
"""
        body_long = """\
add-long v0, v2, v4
sub-long v6, v0, v2
mul-long v8, v0, v6
return-wide v8
"""
        sig_int = compute_minhash(body_int)
        sig_long = compute_minhash(body_long)
        # Both normalize to ALU, ALU, ALU, RET -> identical
        assert sig_int == sig_long

    def test_minhash_different_apis_differ(self):
        """Methods calling different APIs should produce different signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_a = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/crypto/AES;->encrypt([B)[B
invoke-virtual {v0}, Ljava/io/OutputStream;->write([B)V
return-void
"""
        body_b = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Ljava/lang/String;->length()I
invoke-virtual {v0}, Ljava/io/PrintStream;->println(I)V
return-void
"""
        sig_a = compute_minhash(body_a)
        sig_b = compute_minhash(body_b)
        assert sig_a != sig_b

    def test_minhash_too_few_instructions(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        assert compute_minhash("return-void\nnop") is None


class TestACFGBlockFeatures:
    """Tests for per-block ACFG feature extraction via smali_cfg."""

    def test_simple_linear_method(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
add-int v0, v1, v2
invoke-virtual {p0}, Lcom/Foo;->bar()V
return-void
"""
        metrics = compute_cfg_metrics(body)
        assert metrics.block_count >= 1
        assert len(metrics.block_features) == metrics.block_count
        # Each feature vector has 8 elements
        for feat in metrics.block_features:
            assert len(feat) == 8

    def test_branching_method_has_multiple_blocks(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
const/4 v0, 0x0
if-eqz v0, :cond_0
invoke-virtual {p0}, Lcom/Foo;->a()V
goto :goto_0
:cond_0
invoke-virtual {p0}, Lcom/Foo;->b()V
:goto_0
return-void
"""
        metrics = compute_cfg_metrics(body)
        assert metrics.block_count >= 3
        assert len(metrics.block_features) == metrics.block_count

    def test_feature_vector_arithmetic_count(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
add-int v0, v1, v2
sub-int v3, v0, v1
mul-int v4, v0, v3
return v4
"""
        metrics = compute_cfg_metrics(body)
        assert len(metrics.block_features) == 1
        feat = metrics.block_features[0]
        # feat[0] = instr_count (4), feat[1] = arithmetic (3)
        assert feat[0] == 4
        assert feat[1] >= 3  # 3 ALU ops

    def test_feature_vector_call_count(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
invoke-virtual {p0}, Lcom/A;->a()V
invoke-static {v0}, Lcom/B;->b()V
return-void
"""
        metrics = compute_cfg_metrics(body)
        feat = metrics.block_features[0]
        # feat[4] = call count
        assert feat[4] == 2