File size: 2,790 Bytes
0b8f50d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from PIL import Image, UnidentifiedImageError
import io

# Common AI metadata identifiers in image files.
AI_INDICATORS = [
    b'c2pa', b'claim_generator', b'claim_generator_info',
    b'created_software_agent', b'actions.v2', b'assertions',
    b'urn:c2pa', b'jumd', b'jumb', b'jumdcbor', b'jumdc2ma',
    b'jumdc2as', b'jumdc2cl', b'cbor', b'convertedsfwareagent',b'c2pa.version', 
    b'c2pa.assertions', b'c2pa.actions',
    b'c2pa.thumbnail', b'c2pa.signature', b'c2pa.manifest',
    b'c2pa.manifest_store', b'c2pa.ingredient', b'c2pa.parent',
    b'c2pa.provenance', b'c2pa.claim', b'c2pa.hash', b'c2pa.authority',
    b'jumdc2pn', b'jumdrefs', b'jumdver', b'jumdmeta',
    
    
   'midjourney'.encode('utf-8'),
   'stable-diffusion'.encode('utf-8'),
   'stable diffusion'.encode('utf-8'),
   'stable_diffusion'.encode('utf-8'),
   'artbreeder'.encode('utf-8'),
   'runwayml'.encode('utf-8'),
   'remix.ai'.encode('utf-8'),
   'firefly'.encode('utf-8'),
   'adobe_firefly'.encode('utf-8'),

    # OpenAI / DALL·E indicators (all encoded to bytes)
    'openai'.encode('utf-8'),
    'dalle'.encode('utf-8'),
    'dalle2'.encode('utf-8'),
    'DALL-E'.encode('utf-8'),
    'DALL·E'.encode('utf-8'),
    'created_by: openai'.encode('utf-8'),
    'tool: dalle'.encode('utf-8'),
    'tool: dalle2'.encode('utf-8'),
    'creator: openai'.encode('utf-8'),
    'creator: dalle'.encode('utf-8'),
    'openai.com'.encode('utf-8'),
    'api.openai.com'.encode('utf-8'),
    'openai_model'.encode('utf-8'),
    'openai_gpt'.encode('utf-8'),
    
    #Further possible AI-Generation Indicators
    'generated_by'.encode('utf-8'),
    'model_id'.encode('utf-8'),
    'model_version'.encode('utf-8'),
    'model_info'.encode('utf-8'),
    'tool_name'.encode('utf-8'),
    'tool_creator'.encode('utf-8'),
    'tool_version'.encode('utf-8'),
    'model_signature'.encode('utf-8'),
    'ai_model'.encode('utf-8'),
    'ai_tool'.encode('utf-8'),
    'generator'.encode('utf-8'),
    'generated_by_ai'.encode('utf-8'),
    'ai_generated'.encode('utf-8'),
    'ai_art'.encode('utf-8')
    ]


def run_metadata(image_bytes: bytes) -> str:
    try:
        img = Image.open(io.BytesIO(image_bytes))
        img.load()

        exif = img.getexif()
        software = str(exif.get(305, "")).strip()

        suspicious_editors = ["Photoshop", "GIMP", "Snapseed", "Pixlr", "VSCO", "Editor", "Adobe", "Luminar"]

        if any(editor.lower() in software.lower() for editor in suspicious_editors):
            return "edited"

        if any(indicator in image_bytes for indicator in AI_INDICATORS):
            return "ai_generated"

        return "undetermined"

    except UnidentifiedImageError:
        return "error: invalid image format"
    except Exception as e:
        return f"error: {str(e)}"