Skip to content

Commit

Permalink
Revert to Exiftools + logging
Browse files Browse the repository at this point in the history
  • Loading branch information
tiritibambix committed Jan 11, 2025
1 parent 7046308 commit cc49ac2
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 174 deletions.
165 changes: 86 additions & 79 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,41 +82,29 @@ def get_image_dimensions(filepath):
app.logger.error(f"Error getting image dimensions: {str(e)}")
return None, None

def get_available_formats(is_raw=False):
"""Get all formats supported by ImageMagick, with special handling for RAW files."""
def get_available_formats():
"""Get all formats supported by ImageMagick."""
try:
# Récupérer la liste des formats supportés par ImageMagick
result = subprocess.run(['convert', '-list', 'format'], capture_output=True, text=True)
# Exécute la commande magick -list format pour obtenir tous les formats supportés
result = subprocess.run(['magick', '-list', 'format'], capture_output=True, text=True)
formats = []

# Parse la sortie pour extraire les formats
for line in result.stdout.split('\n'):
if line.strip() and not line.startswith(' '):
format_match = re.match(r'^([A-Z0-9]+)\*?\s+[A-Z]\w+\s+(.+)$', line)
if format_match:
format_name = format_match.group(1).lower()
format_desc = format_match.group(2)
if 'write' in format_desc.lower():
formats.append(format_name)
formats.sort()

if is_raw:
# Pour les fichiers RAW, on sépare en formats recommandés et compatibles
recommended_formats = ['jpeg', 'jpg', 'png', 'tiff', 'webp']
other_formats = [f for f in formats if f not in recommended_formats]
return {
'recommended': recommended_formats,
'others': other_formats
}
else:
return formats

# Ignore l'en-tête et les lignes vides
if line.strip() and not line.startswith('Format') and not line.startswith('--'):
# Le format est le premier mot de chaque ligne
format_name = line.split()[0].upper()
# Certains formats ont des suffixes comme * ou +, on les enlève
format_name = format_name.rstrip('*+')
if format_name not in formats:
formats.append(format_name)

return formats
except Exception as e:
app.logger.error(f"Erreur lors de la récupération des formats : {str(e)}")
if is_raw:
return {
'recommended': ['jpeg', 'jpg', 'png', 'tiff', 'webp'],
'others': ['gif', 'bmp']
}
return ['jpeg', 'png', 'gif', 'bmp', 'tiff', 'webp']
app.logger.error(f"Erreur lors de la récupération des formats : {e}")
# Liste de secours avec les formats les plus courants
return ['PNG', 'JPEG', 'GIF', 'TIFF', 'BMP', 'WEBP']

def get_format_categories():
"""Categorize image formats by their typical usage."""
Expand Down Expand Up @@ -337,56 +325,33 @@ def upload_url():

@app.route('/resize_options/<filename>')
def resize_options(filename):
"""Show resize options for a single file."""
try:
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)

# Vérifier si c'est un fichier RAW
is_raw = filename.lower().endswith(('.arw', '.cr2', '.nef', '.dng', '.raw', '.rw2', '.orf', '.pef'))
app.logger.info("RAW file detected" if is_raw else "Non-RAW file detected")

# Obtenir les dimensions de l'image
width, height = get_image_dimensions(filepath)
if width is None or height is None:
width, height = 0, 0 # Valeurs par défaut si impossible d'obtenir les dimensions

# Obtenir les formats disponibles
formats = get_available_formats(is_raw)

return render_template('resize.html',
filename=filename,
original_width=width,
original_height=height,
formats=formats,
is_raw=is_raw,
defaults=DEFAULTS)
except Exception as e:
app.logger.error(f"Error showing resize options: {str(e)}")
flash_error(f"Error showing resize options: {str(e)}")
"""Resize options page for a single image."""
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
dimensions = get_image_dimensions(filepath)
if not dimensions:
return redirect(url_for('index'))

@app.route('/resize_batch_options/<filenames>')
def resize_batch_options(filenames):
"""Show resize options for multiple files."""
try:
filelist = filenames.split(',')

# Vérifier si au moins un fichier est RAW
has_raw = any(f.lower().endswith(('.arw', '.cr2', '.nef', '.dng', '.raw', '.rw2', '.orf', '.pef'))
for f in filelist)

# Obtenir les formats disponibles
formats = get_available_formats(has_raw)

return render_template('resize_batch.html',
filenames=filelist,
formats=formats,
is_raw=has_raw,
defaults=DEFAULTS)
except Exception as e:
app.logger.error(f"Error showing batch resize options: {str(e)}")
flash_error(f"Error showing batch resize options: {str(e)}")
return redirect(url_for('index'))
# Analyze image and get recommended formats
image_type = analyze_image_type(filepath)
if image_type:
format_info = get_recommended_formats(image_type)
formats = {
'recommended': format_info['recommended'],
'compatible': format_info['compatible']
}
else:
formats = {
'recommended': [],
'compatible': get_available_formats()
}

width, height = dimensions
return render_template('resize.html',
filename=filename,
width=width,
height=height,
formats=formats,
image_type=image_type)

@app.route('/resize/<filename>', methods=['POST'])
def resize_image(filename):
Expand Down Expand Up @@ -416,6 +381,48 @@ def resize_image(filename):
except Exception as e:
return flash_error(f"Error processing image: {e}"), redirect(url_for('resize_options', filename=filename))

@app.route('/resize_batch_options/<filenames>')
def resize_batch_options(filenames):
"""Resize options page for batch processing."""
files = filenames.split(',')

# Analyze each image and get common recommended formats
image_types = []
has_transparency = False
has_photos = False
has_graphics = False

for filename in files:
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
image_type = analyze_image_type(filepath)
if image_type:
image_types.append({'filename': filename, 'type': image_type})
has_transparency = has_transparency or image_type['has_transparency']
has_photos = has_photos or image_type['is_photo']
has_graphics = has_graphics or not image_type['is_photo']

# Create a combined image type for the batch
batch_type = {
'has_transparency': has_transparency,
'is_photo': has_photos,
'original_format': None # Not relevant for batch
}

# Get format recommendations for the batch
format_info = get_recommended_formats(batch_type)

batch_info = {
'has_transparency': has_transparency,
'has_photos': has_photos,
'has_graphics': has_graphics
}

return render_template('resize_batch.html',
files=files,
formats=format_info,
image_types=image_types,
batch_info=batch_info)

@app.route('/resize_batch', methods=['POST'])
def resize_batch():
"""Resize multiple images and compress them into a ZIP."""
Expand Down
99 changes: 52 additions & 47 deletions templates/resize.html
Original file line number Diff line number Diff line change
Expand Up @@ -123,32 +123,6 @@
margin-top: var(--spacing-small);
}

.format-section {
margin: 10px 0;
}
.format-section h3 {
margin-bottom: 5px;
}
.format-options {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.format-option {
padding: 5px 10px;
border: 1px solid #ccc;
border-radius: 3px;
cursor: pointer;
}
.format-option:hover {
background-color: #f0f0f0;
}
.format-option.selected {
background-color: #007bff;
color: white;
border-color: #0056b3;
}

@media (min-width: 768px) {
.container {
max-width: 600px;
Expand Down Expand Up @@ -200,29 +174,60 @@ <h4>Resize Image: {{ filename }}</h4>
<label for="quality">Quality (1-100):</label>
<input type="text" name="quality" id="quality" value="100">
</div>
<div class="format-section">
<h3>Recommended Formats</h3>
<div class="format-options">
{% for fmt in formats.recommended %}
<div class="format-option">
<input type="radio" id="format_{{ fmt }}" name="format" value="{{ fmt }}"
{% if fmt == 'jpeg' %}checked{% endif %}>
<label for="format_{{ fmt }}">{{ fmt.upper() }}</label>
</div>
{% endfor %}
</div>
<div class="form-group">
<label for="format">Convert to format:</label>
<select name="format" id="format">
<option value="">Keep Original</option>
{% if formats.recommended %}
<optgroup label="Recommended Formats">
{% for fmt in formats.recommended %}
<option value="{{ fmt|lower }}">{{ fmt }}
{% if image_type %}
{% if (image_type.has_transparency and fmt in ['PNG', 'WebP', 'AVIF']) %}
(Best for transparency)
{% elif (image_type.is_photo and fmt in ['JPEG', 'WebP', 'AVIF']) %}
(Best for photos)
{% elif (not image_type.is_photo and fmt in ['PNG', 'GIF', 'WebP']) %}
(Best for graphics)
{% endif %}
{% endif %}
</option>
{% endfor %}
</optgroup>
{% endif %}
{% if formats.compatible %}
<optgroup label="Other Compatible Formats">
{% for fmt in formats.compatible %}
<option value="{{ fmt|lower }}">{{ fmt }}
{% if image_type %}
{% if (image_type.has_transparency and fmt == 'GIF') %}
(Limited transparency)
{% elif (image_type.is_photo) %}
(Less efficient for photos)
{% else %}
(Basic support)
{% endif %}
{% endif %}
</option>
{% endfor %}
</optgroup>
{% endif %}
</select>
</div>
<div class="format-section">
<h3>Other Compatible Formats</h3>
<div class="format-options">
{% for fmt in formats.compatible %}
<div class="format-option">
<input type="radio" id="format_{{ fmt }}" name="format" value="{{ fmt }}">
<label for="format_{{ fmt }}">{{ fmt.upper() }}</label>
</div>
{% endfor %}
{% if image_type %}
<div class="format-info">
<small>
{% if image_type.has_transparency %}
This image contains transparency.
{% endif %}
{% if image_type.is_photo %}
This appears to be a photographic image.
{% else %}
This appears to be a graphic image.
{% endif %}
</small>
</div>
</div>
{% endif %}
</fieldset>

<button type="submit">Resize</button>
Expand Down
Loading

0 comments on commit cc49ac2

Please sign in to comment.