Zelyanoth commited on
Commit
94a7d17
·
1 Parent(s): 4b77a5a

feat: Enhance image handling in post generation and display logic

Browse files
backend/api/posts.py CHANGED
@@ -246,25 +246,36 @@ def get_job_status(job_id):
246
  # Handle image_data which could be bytes or a URL string
247
  image_data = job['result'].get('image_data')
248
  if isinstance(image_data, bytes):
249
- # If it's bytes, we can't send it directly in JSON
250
- # For now, we'll set it to None and let the frontend know
251
- # In a future update, we might save it to storage and return a URL
252
- response_data['image_url'] = None
253
- response_data['has_image_data'] = True # Flag to indicate image data exists
 
 
 
 
 
 
 
 
254
  elif isinstance(image_data, dict):
255
  # Handle the case where image_data is a dict from Gradio API
256
  # The dict may contain 'path', 'url', or other keys
257
  if image_data.get('url'):
258
  response_data['image_url'] = image_data['url']
259
  response_data['has_image_data'] = True
 
260
  elif image_data.get('path'):
261
  # If we have a path, we might need to serve it or convert it to a URL
262
  # For now, we'll just indicate that image data exists
263
  response_data['image_url'] = None
264
  response_data['has_image_data'] = True
 
265
  else:
266
  response_data['image_url'] = None
267
  response_data['has_image_data'] = image_data is not None
 
268
  elif isinstance(image_data, str):
269
  # Check if it's a local file path
270
  if os.path.exists(image_data):
@@ -272,14 +283,17 @@ def get_job_status(job_id):
272
  job['image_file_path'] = image_data
273
  response_data['image_url'] = f"/api/posts/image/{job_id}" # API endpoint to serve the image
274
  response_data['has_image_data'] = True
 
275
  else:
276
- # If it's a URL, use it directly
277
  response_data['image_url'] = image_data
278
  response_data['has_image_data'] = True
 
279
  else:
280
  # If it's None or other type
281
  response_data['image_url'] = None
282
  response_data['has_image_data'] = image_data is not None
 
283
  else:
284
  response_data['content'] = job['result']
285
  response_data['image_url'] = None
 
246
  # Handle image_data which could be bytes or a URL string
247
  image_data = job['result'].get('image_data')
248
  if isinstance(image_data, bytes):
249
+ # Convert bytes to base64 for sending in JSON
250
+ try:
251
+ # Encode bytes to base64 string
252
+ base64_image = base64.b64encode(image_data).decode('utf-8')
253
+ # Create a data URL for the image
254
+ response_data['image_url'] = f"data:image/png;base64,{base64_image}"
255
+ response_data['has_image_data'] = True
256
+ # Also include the raw image_data for the frontend
257
+ response_data['image_data'] = response_data['image_url']
258
+ except Exception as e:
259
+ current_app.logger.error(f"Error encoding image to base64: {str(e)}")
260
+ response_data['image_url'] = None
261
+ response_data['has_image_data'] = True
262
  elif isinstance(image_data, dict):
263
  # Handle the case where image_data is a dict from Gradio API
264
  # The dict may contain 'path', 'url', or other keys
265
  if image_data.get('url'):
266
  response_data['image_url'] = image_data['url']
267
  response_data['has_image_data'] = True
268
+ response_data['image_data'] = image_data['url']
269
  elif image_data.get('path'):
270
  # If we have a path, we might need to serve it or convert it to a URL
271
  # For now, we'll just indicate that image data exists
272
  response_data['image_url'] = None
273
  response_data['has_image_data'] = True
274
+ response_data['image_data'] = image_data['path']
275
  else:
276
  response_data['image_url'] = None
277
  response_data['has_image_data'] = image_data is not None
278
+ response_data['image_data'] = image_data
279
  elif isinstance(image_data, str):
280
  # Check if it's a local file path
281
  if os.path.exists(image_data):
 
283
  job['image_file_path'] = image_data
284
  response_data['image_url'] = f"/api/posts/image/{job_id}" # API endpoint to serve the image
285
  response_data['has_image_data'] = True
286
+ response_data['image_data'] = image_data
287
  else:
288
+ # If it's a URL or base64 data, use it directly
289
  response_data['image_url'] = image_data
290
  response_data['has_image_data'] = True
291
+ response_data['image_data'] = image_data
292
  else:
293
  # If it's None or other type
294
  response_data['image_url'] = None
295
  response_data['has_image_data'] = image_data is not None
296
+ response_data['image_data'] = image_data
297
  else:
298
  response_data['content'] = job['result']
299
  response_data['image_url'] = None
frontend/src/pages/Posts.jsx CHANGED
@@ -344,20 +344,40 @@ const Posts = () => {
344
  </div>
345
 
346
  {/* Image Preview */}
347
- {postImage && postImage !== 'HAS_IMAGE_DATA_BUT_NOT_URL' && (
348
  <div className="space-y-3 sm:space-y-4">
349
  <label className="block text-xs sm:text-sm font-semibold text-gray-700">Generated Image</label>
350
  <div className="relative border border-gray-300 rounded-xl overflow-hidden bg-gray-50">
351
- <img
352
- src={postImage}
353
- alt="Generated post content"
354
- className="w-full max-h-96 object-contain"
355
- onError={(e) => {
356
- // If image fails to load, remove it from state
357
- setPostImage(null);
358
- e.target.style.display = 'none';
359
- }}
360
- />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  <div className="absolute top-2 right-2 bg-black/50 text-white text-xs px-2 py-1 rounded">
362
  AI Generated
363
  </div>
@@ -365,22 +385,6 @@ const Posts = () => {
365
  </div>
366
  )}
367
 
368
- {/* Image Data Exists Message */}
369
- {postImage === 'HAS_IMAGE_DATA_BUT_NOT_URL' && (
370
- <div className="space-y-3 sm:space-y-4">
371
- <label className="block text-xs sm:text-sm font-semibold text-gray-700">Generated Image</label>
372
- <div className="relative border border-gray-300 rounded-xl overflow-hidden bg-gray-50 p-4">
373
- <div className="text-center text-gray-500">
374
- <svg className="w-12 h-12 mx-auto mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
375
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
376
- </svg>
377
- <p className="text-sm">Image data exists but cannot be displayed directly</p>
378
- <p className="text-xs mt-1">The image will be included when you publish the post</p>
379
- </div>
380
- </div>
381
- </div>
382
- )}
383
-
384
  {/* Create Post Form */}
385
  <form onSubmit={handleCreatePost} className="create-post-form grid grid-cols-1 sm:grid-cols-3 gap-3 sm:gap-4">
386
  <div className="form-field sm:col-span-2">
 
344
  </div>
345
 
346
  {/* Image Preview */}
347
+ {postImage && (
348
  <div className="space-y-3 sm:space-y-4">
349
  <label className="block text-xs sm:text-sm font-semibold text-gray-700">Generated Image</label>
350
  <div className="relative border border-gray-300 rounded-xl overflow-hidden bg-gray-50">
351
+ {/* Check if postImage is a data URL (base64) or a regular URL */}
352
+ {postImage.startsWith('data:image') ? (
353
+ // Display base64 image directly
354
+ <img
355
+ src={postImage}
356
+ alt="Generated post content"
357
+ className="w-full max-h-96 object-contain"
358
+ />
359
+ ) : postImage !== 'HAS_IMAGE_DATA_BUT_NOT_URL' ? (
360
+ // Display regular URL image
361
+ <img
362
+ src={postImage}
363
+ alt="Generated post content"
364
+ className="w-full max-h-96 object-contain"
365
+ onError={(e) => {
366
+ // If image fails to load, remove it from state
367
+ setPostImage(null);
368
+ e.target.style.display = 'none';
369
+ }}
370
+ />
371
+ ) : (
372
+ // Display message for image data that exists but can't be displayed directly
373
+ <div className="text-center text-gray-500 p-4">
374
+ <svg className="w-12 h-12 mx-auto mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
375
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
376
+ </svg>
377
+ <p className="text-sm">Image data exists but cannot be displayed directly</p>
378
+ <p className="text-xs mt-1">The image will be included when you publish the post</p>
379
+ </div>
380
+ )}
381
  <div className="absolute top-2 right-2 bg-black/50 text-white text-xs px-2 py-1 rounded">
382
  AI Generated
383
  </div>
 
385
  </div>
386
  )}
387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  {/* Create Post Form */}
389
  <form onSubmit={handleCreatePost} className="create-post-form grid grid-cols-1 sm:grid-cols-3 gap-3 sm:gap-4">
390
  <div className="form-field sm:col-span-2">
frontend/src/services/postService.js CHANGED
@@ -94,7 +94,17 @@ class PostService {
94
  imageData = jobData.image_url;
95
  } else if (jobData.has_image_data) {
96
  // Special marker for image data that exists but can't be displayed directly
97
- imageData = 'HAS_IMAGE_DATA_BUT_NOT_URL';
 
 
 
 
 
 
 
 
 
 
98
  }
99
 
100
  // If content is an array, take the first element
 
94
  imageData = jobData.image_url;
95
  } else if (jobData.has_image_data) {
96
  // Special marker for image data that exists but can't be displayed directly
97
+ // If we have actual image data (possibly base64), we should handle it
98
+ if (jobData.image_data) {
99
+ // Check if it's base64 encoded data
100
+ if (typeof jobData.image_data === 'string' && jobData.image_data.startsWith('data:image')) {
101
+ imageData = jobData.image_data; // Use the base64 data directly
102
+ } else {
103
+ imageData = 'HAS_IMAGE_DATA_BUT_NOT_URL';
104
+ }
105
+ } else {
106
+ imageData = 'HAS_IMAGE_DATA_BUT_NOT_URL';
107
+ }
108
  }
109
 
110
  // If content is an array, take the first element