jclyo1 commited on
Commit
b16d75f
1 Parent(s): c9a473f
main.py CHANGED
@@ -37,63 +37,46 @@ def generate_image(prompt, model):
37
  filename = str(uuid.uuid4()) + ".jpg"
38
  image.save(filename)
39
 
40
- assertion = {
41
- "assertions": [
42
- {
43
- "label": "com.truepic.custom.ai",
44
- "data": {
45
- "model_name": modelName,
46
- "model_version": modelVersion,
47
- "prompt": prompt,
48
- },
49
- }
50
- ]
51
- }
52
-
53
- json_object = json.dumps(assertion)
54
 
55
  subprocess.check_output(
56
  [
57
- "./truepic",
58
- "sign",
59
  filename,
60
- "--assertions-inline",
61
- json_object,
62
- "--output",
63
- (os.getcwd() + "/static/" + filename),
64
  ]
65
  )
66
 
67
  return {"response": filename}
68
 
 
69
  @app.post("/verify")
70
  def verify_image(fileUpload: UploadFile):
71
  logging.warning("in verify")
72
  logging.warning(fileUpload.filename)
73
-
74
-
75
 
76
  # check if the file has been uploaded
77
  if fileUpload.filename:
78
  # strip the leading path from the file name
79
  fn = os.path.basename(fileUpload.filename)
80
-
81
  # open read and write the file into the server
82
- open(fn, 'wb').write(fileUpload.file.read())
83
-
84
- # subprocess.check_output(
85
- # [
86
- # "./truepic",
87
- # "sign",
88
- # fileUpload.filename,
89
- # "--output",
90
- # (os.getcwd() + "/static/" + fileUpload.filename),
91
- # ]
92
- # )
93
-
94
- #call steg sign script
95
  response = subprocess.check_output(
96
- [
97
  "./scripts/verify.sh",
98
  fileUpload.filename,
99
  ]
@@ -103,42 +86,6 @@ def verify_image(fileUpload: UploadFile):
103
 
104
  return {"response": fileUpload.filename}
105
 
106
- @app.post("/sign")
107
- def sign_image(fileUpload: UploadFile):
108
- logging.warning("in sign")
109
- logging.warning(fileUpload.filename)
110
-
111
-
112
-
113
- # check if the file has been uploaded
114
- if fileUpload.filename:
115
- # strip the leading path from the file name
116
- fn = os.path.basename(fileUpload.filename)
117
-
118
- # open read and write the file into the server
119
- open(fn, 'wb').write(fileUpload.file.read())
120
-
121
- # subprocess.check_output(
122
- # [
123
- # "./truepic",
124
- # "sign",
125
- # fileUpload.filename,
126
- # "--output",
127
- # (os.getcwd() + "/static/" + fileUpload.filename),
128
- # ]
129
- # )
130
-
131
- #call steg sign script
132
- response = subprocess.check_output(
133
- [
134
- "./scripts/sign.sh",
135
- fileUpload.filename,
136
- ]
137
- )
138
-
139
- logging.warning(response)
140
-
141
- return {"response": fileUpload.filename}
142
 
143
  app.mount("/", StaticFiles(directory="static", html=True), name="static")
144
 
 
37
  filename = str(uuid.uuid4()) + ".jpg"
38
  image.save(filename)
39
 
40
+ # assertion = {
41
+ # "assertions": [
42
+ # {
43
+ # "label": "com.truepic.custom.ai",
44
+ # "data": {
45
+ # "model_name": modelName,
46
+ # "model_version": modelVersion,
47
+ # "prompt": prompt,
48
+ # },
49
+ # }
50
+ # ]
51
+ # }
52
+
53
+ # json_object = json.dumps(assertion)
54
 
55
  subprocess.check_output(
56
  [
57
+ "./scripts/sign.sh",
 
58
  filename,
 
 
 
 
59
  ]
60
  )
61
 
62
  return {"response": filename}
63
 
64
+
65
  @app.post("/verify")
66
  def verify_image(fileUpload: UploadFile):
67
  logging.warning("in verify")
68
  logging.warning(fileUpload.filename)
 
 
69
 
70
  # check if the file has been uploaded
71
  if fileUpload.filename:
72
  # strip the leading path from the file name
73
  fn = os.path.basename(fileUpload.filename)
74
+
75
  # open read and write the file into the server
76
+ open(fn, "wb").write(fileUpload.file.read())
77
+
 
 
 
 
 
 
 
 
 
 
 
78
  response = subprocess.check_output(
79
+ [
80
  "./scripts/verify.sh",
81
  fileUpload.filename,
82
  ]
 
86
 
87
  return {"response": fileUpload.filename}
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  app.mount("/", StaticFiles(directory="static", html=True), name="static")
91
 
scripts/sign.sh CHANGED
@@ -1,6 +1,17 @@
1
  #!/usr/bin/env bash
2
 
3
- set -e
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  MEDIA_FILE=$(readlink -f "$1")
6
 
@@ -8,45 +19,68 @@ TRUEPIC_CLI=/home/user/app/truepic
8
  STEG_SCRIPTS=/home/user/app/scripts/
9
  PRIVATE_KEY=/home/user/.truepic/default/private.key
10
 
11
- echo -n "Signing media..."
12
- signed_no_watermark=$(mktemp).jpg
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  ${TRUEPIC_CLI} sign $MEDIA_FILE --output ${signed_no_watermark} > /dev/null 2>&1
14
- echo " --> ${signed_no_watermark}"
15
 
16
- echo
17
- echo -n "Extracting manifest..."
18
  no_watermark_manifest=$(mktemp).bin
19
  ${TRUEPIC_CLI} manifest extract ${signed_no_watermark} --output ${no_watermark_manifest} > /dev/null 2>&1
20
- echo " --> ${no_watermark_manifest}"
21
 
22
- echo
23
- echo -n "Creating watermark signature..."
24
  verification_json=$(${TRUEPIC_CLI} verify ${signed_no_watermark})
 
 
 
 
 
 
 
 
 
 
25
  thumbnail_hash=$(
26
  echo "${verification_json}" | \
27
- jq -r '.manifest_store[0].assertions."c2pa.thumbnail.claim.jpeg"[0].thumbnail_id'
28
  )
29
  timestamp=$(
30
  echo "${verification_json}" | \
31
  jq -r '.manifest_store[0].trusted_timestamp.timestamp'
32
  )
33
- echo -n " ${thumbnail_hash}|${timestamp} ..."
34
- watermark_signature=$(openssl dgst -sha256 -sign ${PRIVATE_KEY} <(echo "${thumbnail_hash}|${timestamp}") | base64)
35
- echo " ${watermark_signature}"
36
-
37
- echo
38
- echo -n "Uploading signed media to steg.ai..."
39
- media_id=$(${STEG_SCRIPTS}/upload.sh ${signed_no_watermark} "image/jpeg")
40
- echo " --> media_id=${media_id}"
41
  rm -f ${signed_no_watermark}
42
 
43
- echo
44
- echo -n "Uploading manifest to steg.ai..."
45
  manifest_id=$(${STEG_SCRIPTS}/upload.sh ${no_watermark_manifest} "application/cbor")
46
- echo " --> media_id=${manifest_id}"
47
 
48
- echo
49
- echo -n "Watermarking media..."
50
  encode_response=$(
51
  curl -s https://api.steg.ai/encode_image_async \
52
  -H "x-api-key: ${STEG_AI_API_KEY}" \
@@ -54,14 +88,13 @@ encode_response=$(
54
  "media_id": "'${media_id}'",
55
  "method": 0,
56
  "owner": "Truepic",
57
- "custom": "{\"manifest_id\":\"'${manifest_id}'\",\"watermark_signature\":\"'${watermark_signature}'\"}"
58
  }'
59
  )
60
- echo "$encode_response" #JCL Debugging
61
  request_id=$(echo "$encode_response" | jq -r '.data.request_id')
62
 
63
  if [ -z "$request_id" ] || [ "$request_id" = "null" ]; then
64
- echo
65
  echo "No request_id"
66
  rm -f ${no_watermark_manifest}
67
  exit 1;
@@ -73,7 +106,7 @@ status_response=""
73
  watermarking_status=""
74
  while [ "$watermarking_status" != "Completed." ]; do
75
  sleep 1
76
- echo -n ".."
77
  status_response=$(
78
  curl -s https://api.steg.ai/media_status?request_id=${request_id} \
79
  -H "x-api-key: ${STEG_AI_API_KEY}"
@@ -82,19 +115,19 @@ while [ "$watermarking_status" != "Completed." ]; do
82
  done
83
 
84
  download_url=$(echo "${status_response}" | jq -r '.data.media_data.media_url')
85
- echo " --> media_id=${watermark_id}"
86
 
87
- echo
88
- echo -n "Downloading watermarked media..."
89
- watermarked_image=$(mktemp).jpg
90
  curl -s -o ${watermarked_image} "$download_url"
91
- echo " --> ${watermarked_image}"
92
 
93
- echo
94
- echo -n "Re-signing the watermarked media..."
95
  ${TRUEPIC_CLI} sign ${watermarked_image} \
96
  --ingredient-manifest-store ${no_watermark_manifest} \
97
- --output output.jpg \
98
  --assertions-inline '{
99
  "assertions": [
100
  {
@@ -102,11 +135,11 @@ ${TRUEPIC_CLI} sign ${watermarked_image} \
102
  "data": {
103
  "actions": [
104
  {
105
- "action": "c2pa.edited",
106
  "when": "@now",
107
  "softwareAgent": "steg.ai",
108
  "parameters": {
109
- "description": "A watermark was applied."
110
  }
111
  }
112
  ]
@@ -114,37 +147,37 @@ ${TRUEPIC_CLI} sign ${watermarked_image} \
114
  }
115
  ]
116
  }' > /dev/null 2>&1
117
- echo " --> output.jpg"
118
  rm -f ${no_watermark_manifest}
119
 
120
- echo
121
- echo -n "Extracting new manifest..."
122
  with_watermark_manifest=$(mktemp).bin
123
- ${TRUEPIC_CLI} manifest extract output.jpg --output ${with_watermark_manifest} > /dev/null 2>&1
124
- echo " --> ${with_watermark_manifest}"
125
 
126
- echo
127
- echo -n "Uploading new manifest to steg.ai..."
128
  new_manifest_id=$(${STEG_SCRIPTS}/upload.sh ${with_watermark_manifest} "application/cbor")
129
- echo " --> media_id=${new_manifest_id}"
130
  rm -f ${with_watermark_manifest}
131
 
132
- echo
133
- echo -n "Updating media with new manifest ID... "
134
  update_result=$(
135
  curl -s https://api.steg.ai/asset \
136
  -X POST \
137
  -H "x-api-key: ${STEG_AI_API_KEY}" \
138
  --data-raw '{
139
  "media_id" : "'${watermark_id}'",
140
- "custom": "{\"manifest_id\":\"'${new_manifest_id}'\",\"watermark_signature\":\"'${watermark_signature}'\"}"
141
  }'
142
  )
143
 
144
- echo ${update_result} | jq -r '.message'
145
 
146
- echo
147
- echo -n "Deleting un-watermarked image (${media_id}) from steg.ai... "
148
  delete_result=$(
149
  curl -s https://api.steg.ai/asset \
150
  -X DELETE \
@@ -154,10 +187,10 @@ delete_result=$(
154
  }'
155
  )
156
 
157
- echo ${delete_result} | jq -r '.message'
158
 
159
- echo
160
- echo -n "Deleting old manifest (${manifest_id}) from steg.ai... "
161
  delete_result=$(
162
  curl -s https://api.steg.ai/asset \
163
  -X DELETE \
@@ -167,4 +200,4 @@ delete_result=$(
167
  }'
168
  )
169
 
170
- echo ${delete_result} | jq -r '.message'
 
1
  #!/usr/bin/env bash
2
 
3
+ if [ "$TRUEPIC_DEBUG" = "2" ]; then
4
+ set -xeo pipefail
5
+ else
6
+ set -eo pipefail
7
+ fi
8
+
9
+ debug_echo() {
10
+ if [ -n "$TRUEPIC_DEBUG" ]; then
11
+ echo "$@"
12
+ fi
13
+ }
14
+
15
 
16
  MEDIA_FILE=$(readlink -f "$1")
17
 
 
19
  STEG_SCRIPTS=/home/user/app/scripts/
20
  PRIVATE_KEY=/home/user/.truepic/default/private.key
21
 
22
+ filename=$(basename "${MEDIA_FILE}")
23
+ extension="${filename##*.}"
24
+ if [ "${extension}" = "jpg" ] || [ "${extension}" = "jpeg" ]; then
25
+ mime_type="image/jpeg"
26
+ else
27
+ if [ "${extension}" = "png" ]; then
28
+ mime_type="image/png"
29
+ else
30
+ echo "Unsupported file extension: ${extension}"
31
+ exit 1
32
+ fi
33
+ fi
34
+
35
+ debug_echo -n "Signing media..."
36
+ signed_no_watermark=$(mktemp).${extension}
37
  ${TRUEPIC_CLI} sign $MEDIA_FILE --output ${signed_no_watermark} > /dev/null 2>&1
38
+ debug_echo " --> ${signed_no_watermark}"
39
 
40
+ debug_echo
41
+ debug_echo -n "Extracting manifest..."
42
  no_watermark_manifest=$(mktemp).bin
43
  ${TRUEPIC_CLI} manifest extract ${signed_no_watermark} --output ${no_watermark_manifest} > /dev/null 2>&1
44
+ debug_echo " --> ${no_watermark_manifest}"
45
 
46
+ debug_echo
47
+ debug_echo -n "Creating watermark signature..."
48
  verification_json=$(${TRUEPIC_CLI} verify ${signed_no_watermark})
49
+ if echo "${verification_json}" | jq -e '.manifest_store[0].assertions."c2pa.thumbnail.claim.jpeg"' >/dev/null; then
50
+ thumbnail_key="c2pa.thumbnail.claim.jpeg"
51
+ else
52
+ if echo "${verification_json}" | jq -e '.manifest_store[0].assertions."c2pa.thumbnail.claim.png"' >/dev/null; then
53
+ thumbnail_key="c2pa.thumbnail.claim.png"
54
+ else
55
+ echo "Couldn't find thumbnail assertion in the C2PA manifest."
56
+ exit 1
57
+ fi
58
+ fi
59
  thumbnail_hash=$(
60
  echo "${verification_json}" | \
61
+ jq -r '.manifest_store[0].assertions."'${thumbnail_key}'"[0].thumbnail_id'
62
  )
63
  timestamp=$(
64
  echo "${verification_json}" | \
65
  jq -r '.manifest_store[0].trusted_timestamp.timestamp'
66
  )
67
+ debug_echo -n " ${thumbnail_hash}|${timestamp} ..."
68
+ watermark_signature=$(openssl dgst -sha256 -sign ${PRIVATE_KEY} <(echo "${thumbnail_hash}|${timestamp}") | base64 | tr -d '\n')
69
+ debug_echo " ${watermark_signature}"
70
+
71
+ debug_echo
72
+ debug_echo -n "Uploading signed media to steg.ai..."
73
+ media_id=$(${STEG_SCRIPTS}/upload.sh ${signed_no_watermark} ${mime_type})
74
+ debug_echo " --> media_id=${media_id}"
75
  rm -f ${signed_no_watermark}
76
 
77
+ debug_echo
78
+ debug_echo -n "Uploading manifest to steg.ai..."
79
  manifest_id=$(${STEG_SCRIPTS}/upload.sh ${no_watermark_manifest} "application/cbor")
80
+ debug_echo " --> media_id=${manifest_id}"
81
 
82
+ debug_echo
83
+ debug_echo -n "Watermarking media..."
84
  encode_response=$(
85
  curl -s https://api.steg.ai/encode_image_async \
86
  -H "x-api-key: ${STEG_AI_API_KEY}" \
 
88
  "media_id": "'${media_id}'",
89
  "method": 0,
90
  "owner": "Truepic",
91
+ "custom": "{\"manifest_id\":\"'${manifest_id}'\",\"watermark_signature\": \"'${watermark_signature}'\"}"
92
  }'
93
  )
 
94
  request_id=$(echo "$encode_response" | jq -r '.data.request_id')
95
 
96
  if [ -z "$request_id" ] || [ "$request_id" = "null" ]; then
97
+ debug_echo
98
  echo "No request_id"
99
  rm -f ${no_watermark_manifest}
100
  exit 1;
 
106
  watermarking_status=""
107
  while [ "$watermarking_status" != "Completed." ]; do
108
  sleep 1
109
+ debug_echo -n ".."
110
  status_response=$(
111
  curl -s https://api.steg.ai/media_status?request_id=${request_id} \
112
  -H "x-api-key: ${STEG_AI_API_KEY}"
 
115
  done
116
 
117
  download_url=$(echo "${status_response}" | jq -r '.data.media_data.media_url')
118
+ debug_echo " --> media_id=${watermark_id}"
119
 
120
+ debug_echo
121
+ debug_echo -n "Downloading watermarked media..."
122
+ watermarked_image=$(mktemp).${extension}
123
  curl -s -o ${watermarked_image} "$download_url"
124
+ debug_echo " --> ${watermarked_image}"
125
 
126
+ debug_echo
127
+ debug_echo -n "Re-signing the watermarked media..."
128
  ${TRUEPIC_CLI} sign ${watermarked_image} \
129
  --ingredient-manifest-store ${no_watermark_manifest} \
130
+ --output output.${extension} \
131
  --assertions-inline '{
132
  "assertions": [
133
  {
 
135
  "data": {
136
  "actions": [
137
  {
138
+ "action": "ai.steg.watermark",
139
  "when": "@now",
140
  "softwareAgent": "steg.ai",
141
  "parameters": {
142
+ "description": "An imperceptible digital watermark was added to the file, which can be used to retrieve information later."
143
  }
144
  }
145
  ]
 
147
  }
148
  ]
149
  }' > /dev/null 2>&1
150
+ debug_echo " --> output.${extension}"
151
  rm -f ${no_watermark_manifest}
152
 
153
+ debug_echo
154
+ debug_echo -n "Extracting new manifest..."
155
  with_watermark_manifest=$(mktemp).bin
156
+ ${TRUEPIC_CLI} manifest extract output.${extension} --output ${with_watermark_manifest} > /dev/null 2>&1
157
+ debug_echo " --> ${with_watermark_manifest}"
158
 
159
+ debug_echo
160
+ debug_echo -n "Uploading new manifest to steg.ai..."
161
  new_manifest_id=$(${STEG_SCRIPTS}/upload.sh ${with_watermark_manifest} "application/cbor")
162
+ debug_echo " --> media_id=${new_manifest_id}"
163
  rm -f ${with_watermark_manifest}
164
 
165
+ debug_echo
166
+ debug_echo -n "Updating media with new manifest ID... "
167
  update_result=$(
168
  curl -s https://api.steg.ai/asset \
169
  -X POST \
170
  -H "x-api-key: ${STEG_AI_API_KEY}" \
171
  --data-raw '{
172
  "media_id" : "'${watermark_id}'",
173
+ "custom": "{\"manifest_id\":\"'${new_manifest_id}'\",\"watermark_signature\":\"'${watermark_signature}'\",\"original_id\":\"'${watermark_id}'\"}"
174
  }'
175
  )
176
 
177
+ debug_echo ${update_result} | jq -r '.message'
178
 
179
+ debug_echo
180
+ debug_echo -n "Deleting un-watermarked image (${media_id}) from steg.ai... "
181
  delete_result=$(
182
  curl -s https://api.steg.ai/asset \
183
  -X DELETE \
 
187
  }'
188
  )
189
 
190
+ if [ -n "$TRUEPIC_DEBUG" ]; then echo ${delete_result} | jq -r '.message'; fi
191
 
192
+ debug_echo
193
+ debug_echo -n "Deleting old manifest (${manifest_id}) from steg.ai... "
194
  delete_result=$(
195
  curl -s https://api.steg.ai/asset \
196
  -X DELETE \
 
200
  }'
201
  )
202
 
203
+ if [ -n "$TRUEPIC_DEBUG" ]; then echo ${delete_result} | jq -r '.message'; fi
scripts/verify.sh CHANGED
@@ -1,32 +1,55 @@
1
  #!/usr/bin/env bash
2
 
3
- set -e
 
 
 
 
 
 
 
 
 
 
4
 
5
  MEDIA_FILE=$(readlink -f "$1")
6
 
7
  TRUEPIC_CLI=/home/user/app/truepic
8
  STEG_SCRIPTS=/home/user/app/scripts/
9
 
10
- echo -n "Checking for C2PA data in the media..."
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  set +e
12
  verification_json=$(${TRUEPIC_CLI} verify $MEDIA_FILE 2>&1)
13
  set -e
14
 
15
  if jq -e . <<< "$verification_json" >/dev/null 2>&1; then
16
- echo " embedded C2PA manifest found."
17
- echo
18
- echo ${verification_json} | jq
19
- exit 0
 
20
  fi
21
- echo " no embedded C2PA manifest found."
22
 
23
- echo
24
- echo -n "Uploading media to steg.ai..."
25
- media_id=$(${STEG_SCRIPTS}/upload.sh ${MEDIA_FILE} "image/jpeg")
26
- echo " --> media_id=${media_id}"
27
 
28
- echo
29
- echo -n "Detecting a watermark..."
30
  decode_response=$(
31
  curl -s https://api.steg.ai/decode_image_async \
32
  -H "x-api-key: ${STEG_AI_API_KEY}" \
@@ -35,7 +58,7 @@ decode_response=$(
35
  request_id=$(echo "$decode_response" | jq -r '.data.request_id')
36
 
37
  if [ -z "$request_id" ] || [ "$request_id" = "null" ]; then
38
- echo
39
  echo "No request_id"
40
  exit 1;
41
  fi
@@ -44,7 +67,7 @@ status_response=""
44
  decode_status=""
45
  while [ "$decode_status" != "Completed." ]; do
46
  sleep 1
47
- echo -n ".."
48
  status_response=$(
49
  curl -s https://api.steg.ai/media_status?request_id=${request_id} \
50
  -H "x-api-key: ${STEG_AI_API_KEY}"
@@ -52,18 +75,19 @@ while [ "$decode_status" != "Completed." ]; do
52
  decode_status=$(echo "${status_response}" | jq -r '.data.status')
53
  done
54
 
 
55
  manifest_id=$(echo "${status_response}" | jq -r '.data.media_data.custom' | jq -r '.manifest_id')
56
  watermark_signature=$(echo "${status_response}" | jq -r '.data.media_data.custom' | jq -r '.watermark_signature')
57
 
58
  if [ -z "$manifest_id" ] || [ "$manifest_id" = "null" ]; then
59
- echo
60
- echo "No manifest_id"
61
  else
62
- echo " --> media_id=${manifest_id}"
63
  fi
64
 
65
- echo
66
- echo -n "Deleting uploaded media (${media_id}) from steg.ai... "
67
  delete_result=$(
68
  curl -s https://api.steg.ai/asset \
69
  -X DELETE \
@@ -72,36 +96,59 @@ delete_result=$(
72
  "media_id" : "'${media_id}'"
73
  }'
74
  )
 
75
 
76
  if [ -z "$manifest_id" ] || [ "$manifest_id" = "null" ]; then
77
- exit 1
 
 
 
78
  fi
79
 
80
- echo ${delete_result} | jq -r '.message'
81
- echo
82
- echo -n "Downloading manifest..."
 
 
 
 
 
 
 
83
  manifest_info=$(curl -s https://api.steg.ai/asset?media_id=${manifest_id} -H "x-api-key: ${STEG_AI_API_KEY}")
84
  manifest_url=$(echo ${manifest_info} | jq -r '.data[0].path')
85
  downloaded_manifest=$(mktemp).bin
86
  curl -s -o ${downloaded_manifest} ${manifest_url}
87
- echo " --> ${downloaded_manifest}"
88
 
89
- echo
90
- echo -n "Inserting manifest into media file..."
91
- ${TRUEPIC_CLI} manifest insert ${downloaded_manifest} $MEDIA_FILE --output re_inserted_image.jpg > /dev/null 2>&1
92
- echo " --> re_inserted_image.jpg"
 
 
93
 
94
- echo
95
- echo "Checking the manifest."
96
- verification_json=$(${TRUEPIC_CLI} verify re_inserted_image.jpg)
97
 
98
  hash_status=$(
99
  echo "${verification_json}" | \
100
  jq -r '.manifest_store[] | select(.is_active == true) | .assertions."c2pa.hash.data"[0].status'
101
  )
 
 
 
 
 
 
 
 
 
 
102
  thumbnail_hash=$(
103
  echo "${verification_json}" | \
104
- jq -r '.manifest_store[0].assertions."c2pa.thumbnail.claim.jpeg"[0].thumbnail_id'
105
  )
106
  timestamp=$(
107
  echo "${verification_json}" | \
@@ -114,7 +161,7 @@ public_key=$(
114
  openssl x509 -pubkey -noout
115
  )
116
 
117
- echo -n "Checking watermark signature... ${thumbnail_hash}|${timestamp} ... ${watermark_signature} ..."
118
  signature_verification=$(
119
  openssl dgst -sha256 \
120
  -verify <(echo "${public_key}") \
@@ -122,44 +169,22 @@ signature_verification=$(
122
  <(echo "${thumbnail_hash}|${timestamp}")
123
  )
124
 
125
- echo " ${signature_verification}"
 
 
 
 
 
126
 
127
- echo -n "Checking image hash..."
128
  if [ "$hash_status" = "VALID" ]; then
129
- echo " hashes match."
130
- echo "${verification_json}" | jq
131
- rm -f ${downloaded_manifest}
 
 
 
132
  exit 0
133
  fi
134
- echo " hashes DON'T match!"
135
- rm -f re_inserted_image.jpg
136
-
137
- echo
138
- echo -n "Re-signing the watermarked media..."
139
- ${TRUEPIC_CLI} sign ${MEDIA_FILE} \
140
- --ingredient-manifest-store ${downloaded_manifest} \
141
- --output re_signed_image.jpg \
142
- --assertions-inline '{
143
- "assertions": [
144
- {
145
- "label": "c2pa.actions",
146
- "data": {
147
- "actions": [
148
- {
149
- "action": "c2pa.unknown",
150
- "when": "@now",
151
- "parameters": {
152
- "description": "Some unknown edits have been made between watermarking and now."
153
- }
154
- }
155
- ]
156
- }
157
- }
158
- ]
159
- }' > /dev/null 2>&1
160
- echo " --> re_signed_image.jpg"
161
- rm -f ${downloaded_manifest}
162
-
163
- echo
164
- echo "Checking the manifest..."
165
- ${TRUEPIC_CLI} verify re_signed_image.jpg | jq
 
1
  #!/usr/bin/env bash
2
 
3
+ if [ "$TRUEPIC_DEBUG" = "2" ]; then
4
+ set -xeo pipefail
5
+ else
6
+ set -eo pipefail
7
+ fi
8
+
9
+ debug_echo() {
10
+ if [ -n "$TRUEPIC_DEBUG" ]; then
11
+ echo "$@"
12
+ fi
13
+ }
14
 
15
  MEDIA_FILE=$(readlink -f "$1")
16
 
17
  TRUEPIC_CLI=/home/user/app/truepic
18
  STEG_SCRIPTS=/home/user/app/scripts/
19
 
20
+ filename=$(basename "${MEDIA_FILE}")
21
+ extension="${filename##*.}"
22
+ if [ "${extension}" = "jpg" ] || [ "${extension}" = "jpeg" ]; then
23
+ mime_type="image/jpeg"
24
+ else
25
+ if [ "${extension}" = "png" ]; then
26
+ mime_type="image/png"
27
+ else
28
+ echo "Unsupported file extension: ${extension}"
29
+ exit 1
30
+ fi
31
+ fi
32
+
33
+ debug_echo -n "Checking for C2PA data in the media..."
34
  set +e
35
  verification_json=$(${TRUEPIC_CLI} verify $MEDIA_FILE 2>&1)
36
  set -e
37
 
38
  if jq -e . <<< "$verification_json" >/dev/null 2>&1; then
39
+ c2pa_manifest_found=true
40
+ debug_echo " embedded C2PA manifest found."
41
+ else
42
+ c2pa_manifest_found=false
43
+ debug_echo " no embedded C2PA manifest found."
44
  fi
 
45
 
46
+ debug_echo
47
+ debug_echo -n "Uploading media to steg.ai..."
48
+ media_id=$(${STEG_SCRIPTS}/upload.sh ${MEDIA_FILE} $mime_type)
49
+ debug_echo " --> media_id=${media_id}"
50
 
51
+ debug_echo
52
+ debug_echo -n "Detecting a watermark..."
53
  decode_response=$(
54
  curl -s https://api.steg.ai/decode_image_async \
55
  -H "x-api-key: ${STEG_AI_API_KEY}" \
 
58
  request_id=$(echo "$decode_response" | jq -r '.data.request_id')
59
 
60
  if [ -z "$request_id" ] || [ "$request_id" = "null" ]; then
61
+ debug_echo
62
  echo "No request_id"
63
  exit 1;
64
  fi
 
67
  decode_status=""
68
  while [ "$decode_status" != "Completed." ]; do
69
  sleep 1
70
+ debug_echo -n ".."
71
  status_response=$(
72
  curl -s https://api.steg.ai/media_status?request_id=${request_id} \
73
  -H "x-api-key: ${STEG_AI_API_KEY}"
 
75
  decode_status=$(echo "${status_response}" | jq -r '.data.status')
76
  done
77
 
78
+ original_id=$(echo "${status_response}" | jq -r '.data.media_data.custom' | jq -r '.original_id')
79
  manifest_id=$(echo "${status_response}" | jq -r '.data.media_data.custom' | jq -r '.manifest_id')
80
  watermark_signature=$(echo "${status_response}" | jq -r '.data.media_data.custom' | jq -r '.watermark_signature')
81
 
82
  if [ -z "$manifest_id" ] || [ "$manifest_id" = "null" ]; then
83
+ debug_echo
84
+ debug_echo "No manifest_id"
85
  else
86
+ debug_echo " --> media_id=${manifest_id}"
87
  fi
88
 
89
+ debug_echo
90
+ debug_echo -n "Deleting uploaded media (${media_id}) from steg.ai... "
91
  delete_result=$(
92
  curl -s https://api.steg.ai/asset \
93
  -X DELETE \
 
96
  "media_id" : "'${media_id}'"
97
  }'
98
  )
99
+ if [ -n "${TRUEPIC_DEBUG}" ]; then echo ${delete_result} | jq -r '.message'; fi
100
 
101
  if [ -z "$manifest_id" ] || [ "$manifest_id" = "null" ]; then
102
+ echo "Contains C2PA manifest: ${c2pa_manifest_found}"
103
+ echo "Contains watermark: false"
104
+ echo "Original watermarked media: n/a"
105
+ exit 0
106
  fi
107
 
108
+ debug_echo
109
+ debug_echo -n "Downloading original watermarked media..."
110
+ original_info=$(curl -s https://api.steg.ai/asset?media_id=${original_id} -H "x-api-key: ${STEG_AI_API_KEY}")
111
+ original_url=$(echo ${original_info} | jq -r '.data[0].path')
112
+ downloaded_original=$(mktemp).${extension}
113
+ curl -s -o ${downloaded_original} ${original_url}
114
+ debug_echo " --> ${downloaded_original}"
115
+
116
+ debug_echo
117
+ debug_echo -n "Downloading new manifest..."
118
  manifest_info=$(curl -s https://api.steg.ai/asset?media_id=${manifest_id} -H "x-api-key: ${STEG_AI_API_KEY}")
119
  manifest_url=$(echo ${manifest_info} | jq -r '.data[0].path')
120
  downloaded_manifest=$(mktemp).bin
121
  curl -s -o ${downloaded_manifest} ${manifest_url}
122
+ debug_echo " --> ${downloaded_manifest}"
123
 
124
+ debug_echo
125
+ debug_echo -n "Inserting new manifest into media file..."
126
+ ${TRUEPIC_CLI} manifest insert ${downloaded_manifest} ${downloaded_original} --output watermarked_original.${extension} > /dev/null 2>&1
127
+ debug_echo " --> watermarked_original.${extension}"
128
+ rm -f ${downloaded_original}
129
+ rm -f ${downloaded_manifest}
130
 
131
+ debug_echo
132
+ debug_echo "Checking the manifest."
133
+ verification_json=$(${TRUEPIC_CLI} verify watermarked_original.${extension})
134
 
135
  hash_status=$(
136
  echo "${verification_json}" | \
137
  jq -r '.manifest_store[] | select(.is_active == true) | .assertions."c2pa.hash.data"[0].status'
138
  )
139
+ if echo "${verification_json}" | jq -e '.manifest_store[0].assertions."c2pa.thumbnail.claim.jpeg"' >/dev/null; then
140
+ thumbnail_key="c2pa.thumbnail.claim.jpeg"
141
+ else
142
+ if echo "${verification_json}" | jq -e '.manifest_store[0].assertions."c2pa.thumbnail.claim.png"' >/dev/null; then
143
+ thumbnail_key="c2pa.thumbnail.claim.png"
144
+ else
145
+ echo "Couldn't find thumbnail assertion in the C2PA manifest."
146
+ exit 1
147
+ fi
148
+ fi
149
  thumbnail_hash=$(
150
  echo "${verification_json}" | \
151
+ jq -r '.manifest_store[0].assertions."'${thumbnail_key}'"[0].thumbnail_id'
152
  )
153
  timestamp=$(
154
  echo "${verification_json}" | \
 
161
  openssl x509 -pubkey -noout
162
  )
163
 
164
+ debug_echo -n "Checking watermark signature... ${thumbnail_hash}|${timestamp} ... ${watermark_signature} ..."
165
  signature_verification=$(
166
  openssl dgst -sha256 \
167
  -verify <(echo "${public_key}") \
 
169
  <(echo "${thumbnail_hash}|${timestamp}")
170
  )
171
 
172
+ if [ "${signature_verification}" != "Verified OK" ]; then
173
+ debug_echo " FAILED"
174
+ echo "Watermark signature verification failed"
175
+ exit 1
176
+ fi
177
+ debug_echo " ${signature_verification}"
178
 
179
+ debug_echo -n "Checking image hash..."
180
  if [ "$hash_status" = "VALID" ]; then
181
+ debug_echo " hashes match."
182
+ if [ -n "$TRUEPIC_DEBUG" ]; then echo "${verification_json}" | jq; fi
183
+
184
+ echo "Contains C2PA manifest: ${c2pa_manifest_found}"
185
+ echo "Contains watermark: true"
186
+ echo "Original watermarked media: watermarked_original.${extension}"
187
  exit 0
188
  fi
189
+ debug_echo " hashes DON'T match!"
190
+ rm -f watermarked_original.${extension}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
static/images/generate_icon.svg ADDED
static/images/placeholder.png ADDED
static/images/spinner.svg ADDED
static/images/verify_icon.svg ADDED
static/index.html CHANGED
@@ -13,71 +13,246 @@
13
  />
14
 
15
  <script
16
- src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
17
- integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
18
- crossorigin="anonymous"
19
- ></script>
20
 
21
  <link rel="stylesheet" href="style.css" type="text/css" />
22
 
23
  <script
24
- type="module"
25
- src="https://display.truepic.com/truepic_display.es.js"
26
- ></script>
27
- </head>
28
  <body>
29
- <div class="container">
30
- <label class="form-label" for="customFile">Operation</label>
31
- <select class="form-select" id="operation">
32
- <option value="/verify">Verify</option>
33
- <option value="/sign">Sign</option>
34
- </select>
35
- <form method="post" id="fileUploadForm" enctype = "multipart/form-data">
36
- <input type="file" class="form-control" name="fileUpload" id="fileUpload" />
37
- <button class="btn btn-primary" type="submit">Submit</button>
38
- </form>
39
- <div id="image-container"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  </div>
41
-
42
  </body>
43
 
44
  <script>
45
- const form = document.querySelector('#fileUploadForm');
46
- const operation = document.querySelector('#operation');
47
-
48
- form.addEventListener('submit', (e) => {
49
- e.preventDefault();
50
- submitForm();
51
- });
52
-
53
- function submitForm() {
54
- const formData = new FormData(form);
55
-
56
- // Add additional form data as needed
57
- //formData.append('additionalData', 'additionalValue');
58
-
59
- // Call function to submit form data
60
- submitFormData(formData);
61
- }
62
-
63
- function submitFormData(formData) {
64
- console.log("operation", operation.value)
65
-
66
-
67
- fetch(operation.value, {
68
- method: 'POST',
69
- body: formData
70
- })
71
- .then(response => response.json())
72
- .then(data => {
73
- console.log(data)
74
-
75
- const path = "/" + data.response;
76
-
77
- var resultsContainer = document.getElementById("image-container");
78
-
79
- var truepicDisplay = document.createElement("truepic-display");
80
- /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  truepicDisplay.addEventListener(
82
  "validate",
83
  setVerificationOutputFromValidation
@@ -88,21 +263,82 @@ function submitFormData(formData) {
88
  );
89
  */
90
 
91
- truepicDisplay.setAttribute("id", "result");
92
- truepicDisplay.setAttribute("active", "");
93
- var truepic = document.createElement("img");
94
- truepic.src = path;
95
-
96
- truepicDisplay.appendChild(truepic);
97
-
98
- resultsContainer.appendChild(truepicDisplay);
99
- // Handle response data
100
- })
101
- .catch(error => {
102
- console.log(error)
103
- // Handle errors
104
- });
105
- }
106
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  </html>
 
13
  />
14
 
15
  <script
16
+ src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
17
+ integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
18
+ crossorigin="anonymous"
19
+ ></script>
20
 
21
  <link rel="stylesheet" href="style.css" type="text/css" />
22
 
23
  <script
24
+ type="module"
25
+ src="https://display.truepic.com/truepic_display.es.js"
26
+ ></script>
27
+ </head>
28
  <body>
29
+ <div class="container-fluid mt-2" id="head">
30
+ <div class="container">
31
+ <div class="row">
32
+ <div class="col position-relative">
33
+ <div class="row">
34
+ <div class="col">
35
+ <h1>
36
+ Title of Space
37
+ <div class="badge bg-secondary">experimental</div>
38
+ </h1>
39
+ <p>
40
+ Brief intro explaining the high level concept of this tool.
41
+ Eget consequat at proin sed dolor morbi urna. Quam aliquam
42
+ imperdiet est lobortis lectus sit vel.
43
+ </p>
44
+ </div>
45
+ </div>
46
+ <div class="d-flex flex-row position-absolute bottom-0 tabs">
47
+ <div id="generateTab" class="active">
48
+ <img src="images/generate_icon.svg" /> Generate
49
+ </div>
50
+ <div id="verifyTab">
51
+ <img src="images/verify_icon.svg" /> Verify
52
+ </div>
53
+ </div>
54
+ </div>
55
+ <div class="col right-column">
56
+ <div class="alert alert-secondary" role="alert">
57
+ <h4>Support our work!</h4>
58
+ <p>Like this Space in the nav above</p>
59
+ <p>Joining the conversation in the Community tab</p>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </div>
65
+ <div class="container-fluid" id="body">
66
+ <div class="container">
67
+ <div class="row">
68
+ <div class="col">
69
+ <div class="display-generate">
70
+ <div class="image-container">
71
+ <img src="images/placeholder.png" id="placeholder" />
72
+ <img
73
+ src="images/spinner.svg"
74
+ id="spinner"
75
+ style="display: none"
76
+ />
77
+ </div>
78
+ </div>
79
+ <div class="display-verify">
80
+ <div class="image-container"></div>
81
+ </div>
82
+ </div>
83
+ <div class="col right-column">
84
+ <div class="display-generate">
85
+ <form class="image-gen-form">
86
+ <div class="form-group mb-3">
87
+ <label for="prompt">Image prompt</label>
88
+ <textarea id="prompt" class="form-control"></textarea>
89
+ </div>
90
+
91
+ <div class="form-group mb-3">
92
+ <label>Model</label>
93
+ <div class="custom-select">
94
+ <select id="model" class="form-control">
95
+ <option disabled selected value>Select</option>
96
+ <option value="runwayml/stable-diffusion-v1-5,1.5">
97
+ runwayml/stable-diffusion-v1-5
98
+ </option>
99
+ <option value="CompVis/stable-diffusion-v1-4,1.4">
100
+ CompVis/stable-diffusion-v1-4
101
+ </option>
102
+ <option value="stabilityai/stable-diffusion-2-1,2.1">
103
+ stabilityai/stable-diffusion-2-1
104
+ </option>
105
+ </select>
106
+ </div>
107
+ </div>
108
+
109
+ <div class="form-check mb-3">
110
+ <input
111
+ class="form-check-input"
112
+ type="checkbox"
113
+ value=""
114
+ id="terms"
115
+ />
116
+ <label class="form-check-label" for="defaultCheck1">
117
+ By using this demo you agree to the
118
+ <a href="#">Terms and Conditions of Truepic and Steg.AI</a>
119
+ </label>
120
+ </div>
121
+
122
+ <button type="submit" class="btn btn-primary">Submit</button>
123
+ </form>
124
+
125
+ <h3>How it works</h3>
126
+
127
+ <p>
128
+ Images are generated using a hosted model and AI disclosure is
129
+ added to the file. This information, referred to as Content
130
+ Credentials, serves as a nutrition label for the content. We
131
+ employ the tamper-evident open C2PA standard, which utilizes PKI
132
+ and is resistant to forgery. You can download and transfer the
133
+ image to supported editing tools like Photoshop, where your edit
134
+ history can also be securely added to the file. This historical
135
+ information, known as provenance, accompanies your media and can
136
+ be extracted and displayed using a tool or website.
137
+ </p>
138
+ <p>Want to know more? Read our community blog post.</p>
139
+ </div>
140
+ <div class="display-verify">
141
+ <form class="verify-upload-form" enctype="multipart/form-data">
142
+ <div class="form-group mb-3">
143
+ <label>Upload image</label>
144
+ <div class="custom-select">
145
+ <input type="file" class="form-control" />
146
+ </div>
147
+ </div>
148
+
149
+ <div class="form-check mb-3">
150
+ <input
151
+ class="form-check-input"
152
+ type="checkbox"
153
+ value=""
154
+ id="terms"
155
+ />
156
+ <label class="form-check-label" for="defaultCheck1">
157
+ By using this demo you agree to the
158
+ <a href="#">Terms and Conditions of Truepic and Steg.AI</a>
159
+ </label>
160
+ </div>
161
+
162
+ <button type="submit" class="btn btn-primary">Submit</button>
163
+ </form>
164
+
165
+ <h3>How it works</h3>
166
+
167
+ <p>
168
+ Images are generated using a hosted model and AI disclosure is
169
+ added to the file. This information, referred to as Content
170
+ Credentials, serves as a nutrition label for the content. We
171
+ employ the tamper-evident open C2PA standard, which utilizes PKI
172
+ and is resistant to forgery. You can download and transfer the
173
+ image to supported editing tools like Photoshop, where your edit
174
+ history can also be securely added to the file. This historical
175
+ information, known as provenance, accompanies your media and can
176
+ be extracted and displayed using a tool or website.
177
+ </p>
178
+ <p>Want to know more? Read our community blog post.</p>
179
+ </div>
180
+ </div>
181
+ </div>
182
+ </div>
183
  </div>
 
184
  </body>
185
 
186
  <script>
187
+ const generateTab = document.querySelector("#generateTab");
188
+ const verifyTab = document.querySelector("#verifyTab");
189
+ const displayVerify = document.querySelectorAll(".display-verify");
190
+ const displayGenerate = document.querySelectorAll(".display-generate");
191
+ const uploadForm = document.querySelector(".verify-upload-form");
192
+ const imageGenForm = document.querySelector(".image-gen-form");
193
+ const placeholder = document.getElementById("placeholder");
194
+ const spinner = document.getElementById("spinner");
195
+ const imagePrompt = document.getElementById("prompt");
196
+ const model = document.getElementById("model");
197
+
198
+ generateTab.addEventListener("click", (event) => {
199
+ event.target.classList.add("active");
200
+ verifyTab.classList.remove("active");
201
+
202
+ setGenerateElementsDisplay("block");
203
+ setVerifyElementsDisplay("none");
204
+ });
205
+
206
+ verifyTab.addEventListener("click", (event) => {
207
+ event.target.classList.add("active");
208
+ generateTab.classList.remove("active");
209
+
210
+ setGenerateElementsDisplay("none");
211
+ setVerifyElementsDisplay("block");
212
+ });
213
+
214
+ function setGenerateElementsDisplay(displayStatus) {
215
+ displayGenerate.forEach((item) => {
216
+ item.style.display = displayStatus;
217
+ });
218
+ }
219
+
220
+ function setVerifyElementsDisplay(displayStatus) {
221
+ displayVerify.forEach((item) => {
222
+ item.style.display = displayStatus;
223
+ });
224
+ }
225
+
226
+ uploadForm.addEventListener("submit", (e) => {
227
+ e.preventDefault();
228
+ submitForm();
229
+ });
230
+
231
+ function submitForm() {
232
+ const formData = new FormData(uploadForm);
233
+
234
+ // Add additional form data as needed
235
+ //formData.append('additionalData', 'additionalValue');
236
+
237
+ // Call function to submit form data
238
+ submitFormData(formData);
239
+ }
240
+
241
+ function submitFormData(formData) {
242
+ fetch("/verify", {
243
+ method: "POST",
244
+ body: formData,
245
+ })
246
+ .then((response) => response.json())
247
+ .then((data) => {
248
+ console.log(data);
249
+
250
+ const path = "/" + data.response;
251
+
252
+ var resultsContainer = document.getElementById("image-container");
253
+
254
+ var truepicDisplay = document.createElement("truepic-display");
255
+ /*
256
  truepicDisplay.addEventListener(
257
  "validate",
258
  setVerificationOutputFromValidation
 
263
  );
264
  */
265
 
266
+ truepicDisplay.setAttribute("id", "result");
267
+ truepicDisplay.setAttribute("active", "");
268
+ var truepic = document.createElement("img");
269
+ truepic.src = path;
270
+
271
+ truepicDisplay.appendChild(truepic);
272
+
273
+ resultsContainer.appendChild(truepicDisplay);
274
+ // Handle response data
275
+ })
276
+ .catch((error) => {
277
+ console.log(error);
278
+ // Handle errors
279
+ });
280
+ }
281
+
282
+ const generateImage = async (text, model) => {
283
+ const inferResponse = await fetch(
284
+ `generate?prompt=${text}&model=${model}`
285
+ );
286
+ const inferJson = await inferResponse.json();
287
+
288
+ return inferJson.response;
289
+ };
290
+
291
+ imageGenForm.addEventListener("submit", async (event) => {
292
+ event.preventDefault();
293
+
294
+ // verificationDetails.style.display = "none";
295
+ // parameters.style.display = "none";
296
+ // downloadLink.style.display = "none";
297
+
298
+ try {
299
+ if (placeholder) placeholder.remove();
300
 
301
+ if (document.getElementById("result"))
302
+ document.getElementById("result").remove();
303
+ spinner.style.display = "block";
304
+
305
+ const resp = await generateImage(imagePrompt.value, model.value);
306
+ const path = "/" + resp;
307
+
308
+ var resultsContainer = document.getElementById("image-container");
309
+
310
+ var truepicDisplay = document.createElement("truepic-display");
311
+ truepicDisplay.addEventListener(
312
+ "validate",
313
+ setVerificationOutputFromValidation
314
+ );
315
+ truepicDisplay.addEventListener(
316
+ "validate",
317
+ setCertificateOutputFromValidation
318
+ );
319
+
320
+ truepicDisplay.setAttribute("id", "result");
321
+ truepicDisplay.setAttribute("active", "");
322
+ var truepic = document.createElement("img");
323
+ truepic.src = path;
324
+
325
+ truepicDisplay.appendChild(truepic);
326
+
327
+ spinner.style.display = "none";
328
+ resultsContainer.appendChild(truepicDisplay);
329
+
330
+ /*
331
+ downloadLink.style.display = "block";
332
+ downloadLink.href = path;
333
+ downloadLink.download = resp;
334
+
335
+ modelParam.innerHTML = model.value;
336
+ promptParam.innerHTML = textGenInput.value;
337
+ parameters.style.display = "block";
338
+ */
339
+ } catch (err) {
340
+ console.error(err);
341
+ }
342
+ });
343
+ </script>
344
  </html>
static/style.css CHANGED
@@ -1,8 +1,106 @@
1
- #uploaded-image-container {
2
- border-bottom: 1px solid black;
3
- border-top: 1px solid black;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
 
6
- .results {
7
- display: none;
8
  }
 
1
+ @import url("https://fonts.cdnfonts.com/css/inter");
2
+
3
+ body {
4
+ font-family: "Inter", sans-serif;
5
+ }
6
+
7
+ #head {
8
+ padding-top: 1rem;
9
+ border-bottom: 1px solid rgba(227, 234, 240, 1);
10
+ }
11
+
12
+ h1 {
13
+ font-weight: 600;
14
+ font-size: 26px;
15
+ }
16
+
17
+ p {
18
+ font-weight: 400;
19
+ font-size: 16px;
20
+ line-height: 24px;
21
+ }
22
+
23
+ .badge.bg-secondary {
24
+ background-color: rgba(247, 249, 250, 1) !important;
25
+ border-color: rgba(215, 220, 224, 1);
26
+ border: 1px solid rgba(215, 220, 224, 1);
27
+ color: rgba(86, 104, 122, 1);
28
+ text-transform: uppercase;
29
+ font-size: 12px;
30
+ padding: 7px;
31
+ position: relative;
32
+ top: -0.5rem;
33
+ left: 1rem;
34
+ }
35
+
36
+ .tabs div {
37
+ margin-right: 1rem;
38
+ cursor: pointer;
39
+ }
40
+
41
+ .tabs div.active {
42
+ border-bottom: 3px solid rgba(26, 109, 255, 1);
43
+ }
44
+
45
+ .right-column {
46
+ flex: 0 0 465px;
47
+ margin: 1rem;
48
+ }
49
+
50
+ .image-container {
51
+ margin: 2rem 1rem 0 0;
52
+ background: rgba(247, 249, 250, 1);
53
+ display: flex;
54
+ justify-content: center;
55
+ height: 35rem;
56
+ }
57
+
58
+ .image-container img {
59
+ align-self: start;
60
+ width: 100%;
61
+ height: auto;
62
+ }
63
+
64
+ .image-container #placeholder,
65
+ .image-container #spinner {
66
+ width: 48px;
67
+ height: 48px;
68
+ align-self: center;
69
+ }
70
+
71
+ #body .container > .row > .col:first-child {
72
+ border-right: 1px solid rgba(227, 234, 240, 1);
73
+ }
74
+
75
+ .custom-select {
76
+ position: relative;
77
+ }
78
+
79
+ .custom-select::after {
80
+ --size: 0.4rem;
81
+ content: "";
82
+ position: absolute;
83
+ right: 1rem;
84
+ pointer-events: none;
85
+ border-left: var(--size) solid transparent;
86
+ border-right: var(--size) solid transparent;
87
+ border-top: var(--size) solid black;
88
+ top: 30%;
89
+ }
90
+
91
+ label {
92
+ font-size: 14px;
93
+ font-weight: 600;
94
+ }
95
+
96
+ label.form-check-label {
97
+ font-weight: 400;
98
+ }
99
+
100
+ .btn-primary {
101
+ width: 100%;
102
  }
103
 
104
+ .display-verify {
105
+ display: none;
106
  }