diff --git a/modules/hm_qc/checks/__init__.py b/modules/hm_qc/checks/__init__.py index 7a4248e..c08638b 100644 --- a/modules/hm_qc/checks/__init__.py +++ b/modules/hm_qc/checks/__init__.py @@ -3,8 +3,9 @@ # Base check class from .base_check import BaseCheck -# Sample checks +# Checks from .sample_filename_check import FilenameCheck from .sample_quality_check import QualityCheck +from .dimension_check import DimensionCheck -__all__ = ['BaseCheck', 'FilenameCheck', 'QualityCheck'] +__all__ = ['BaseCheck', 'FilenameCheck', 'QualityCheck', 'DimensionCheck'] diff --git a/modules/hm_qc/checks/dimension_check.py b/modules/hm_qc/checks/dimension_check.py new file mode 100644 index 0000000..8c4f182 --- /dev/null +++ b/modules/hm_qc/checks/dimension_check.py @@ -0,0 +1,86 @@ +""" +Dimension Check. + +Validates image dimensions and integrity using PIL. +""" +import os +from typing import Dict, Any +from PIL import Image +from .base_check import BaseCheck + + +class DimensionCheck(BaseCheck): + """Check image dimensions and validate integrity.""" + + # Minimum acceptable dimensions (in pixels) + MIN_WIDTH = 100 + MIN_HEIGHT = 100 + + def __init__(self, name: str = "dimension_check", weight: float = 50.0, config: Dict[str, Any] = None): + super().__init__(name, weight, config) + + def run(self, file_path: str, context: Dict[str, Any]) -> Dict[str, Any]: + """Run dimension validation on an image file.""" + try: + ext = os.path.splitext(file_path)[1].lower() + + if ext not in ['.jpg', '.jpeg', '.png', '.psd']: + return self._create_result( + status='skipped', + score=100.0, + message='Dimension check only applies to image files', + details={'file_type': ext} + ) + + img = Image.open(file_path) + width, height = img.size + mode = img.mode + fmt = img.format or ext.replace('.', '').upper() + + # Store in context for other checks + context['image_dimensions'] = {'width': width, 'height': height} + context['image_info'] = {'mode': mode, 'format': fmt} + + # Validate dimensions + issues = [] + if width < self.MIN_WIDTH: + issues.append(f'Width {width}px is below minimum {self.MIN_WIDTH}px') + if height < self.MIN_HEIGHT: + issues.append(f'Height {height}px is below minimum {self.MIN_HEIGHT}px') + + if issues: + return self._create_result( + status='failed', + score=30.0, + message=f'Image dimensions too small: {width}x{height}', + details={ + 'width': width, + 'height': height, + 'format': fmt, + 'mode': mode, + 'issues': issues + }, + recommendations=['Provide a higher resolution image'] + ) + + return self._create_result( + status='passed', + score=100.0, + message=f'Image dimensions valid: {width}x{height} ({fmt})', + details={ + 'width': width, + 'height': height, + 'format': fmt, + 'mode': mode, + 'megapixels': round((width * height) / 1_000_000, 2) + } + ) + + except Exception as e: + self.logger.error(f"Dimension check error: {e}") + return self._create_result( + status='error', + score=0.0, + message=f'Error reading image: {str(e)}', + details={'error': str(e)} + ) diff --git a/modules/hm_qc/executor.py b/modules/hm_qc/executor.py index 4b3b330..21043a0 100644 --- a/modules/hm_qc/executor.py +++ b/modules/hm_qc/executor.py @@ -11,7 +11,7 @@ import logging from datetime import datetime from typing import Dict, List, Any from .scoring import ScoringEngine -from .checks import FilenameCheck, QualityCheck +from .checks import FilenameCheck, QualityCheck, DimensionCheck from core.utils.progress_tracker import UnifiedProgressTracker from core.models.qc_report import QCReport from core.models.database import db @@ -126,10 +126,11 @@ class QCExecutor: checks = [] profile_checks = self.profile.get('checks', []) - # Map check names to classes (in real implementation, this would be dynamic) check_map = { 'filename_parse': FilenameCheck, - 'quality_check': QualityCheck + 'quality_check': QualityCheck, + 'image_quality': QualityCheck, + 'dimension_check': DimensionCheck } for check_config in profile_checks: diff --git a/modules/hm_qc/profiles/profiles.yaml b/modules/hm_qc/profiles/profiles.yaml index 3a1a575..eedf891 100644 --- a/modules/hm_qc/profiles/profiles.yaml +++ b/modules/hm_qc/profiles/profiles.yaml @@ -1,4 +1,4 @@ -# HM QC Profiles with Weighted Scoring +# HM QC Profiles # # Each profile defines: # - name: Profile display name @@ -6,81 +6,22 @@ # - checks: List of checks with weights and LLM configuration profiles: - standard_pdf: - name: "Standard PDF QC (Demo)" - description: "Demo profile with 2 sample checks" - checks: - - name: "filename_parse" - weight: 40 - enabled: true - llm_provider: null - description: "Validate H&M filename conventions" - - - name: "quality_check" - weight: 60 - enabled: true - llm_provider: "openai" - llm_model: "gpt-4o" - description: "AI-powered quality assessment" - - standard_image: - name: "Standard Image QC" + hm_image_check: + name: "H&M Image Check" description: "Quality checks for H&M image assets (JPG, PNG, PSD)" checks: - - name: "image_parse" - weight: 5 - enabled: true - llm_provider: null - description: "Parse image metadata and properties" - - - name: "filename_parse" - weight: 10 - enabled: true - llm_provider: null - description: "Validate H&M filename conventions" - - name: "dimension_check" - weight: 15 + weight: 50 enabled: true llm_provider: null - description: "Verify image dimensions match filename" + description: "Verify image dimensions and integrity" - name: "image_quality" - weight: 30 + weight: 50 enabled: true llm_provider: "openai" llm_model: "gpt-4o" - description: "Assess image quality and resolution" + description: "AI-powered image quality and legibility assessment" - - name: "censorship_check" - weight: 40 - enabled: true - llm_provider: "openai" - llm_model: "gpt-4o" - description: "Check body coverage requirements (CEN markets only)" - - quick_check: - name: "Quick Check" - description: "Fast validation of essential requirements only" - checks: - - name: "filename_parse" - weight: 30 - enabled: true - llm_provider: null - description: "Validate filename conventions" - - - name: "dimension_check" - weight: 35 - enabled: true - llm_provider: null - description: "Verify dimensions" - - - name: "language_validate" - weight: 35 - enabled: true - llm_provider: "openai" - llm_model: "gpt-4o" - description: "Validate language" - -# Note: Weights should sum to approximately 100 for each profile +# Note: Weights should sum to 100 for each profile # Higher weight = more important to overall score diff --git a/modules/hm_qc/templates/hm_qc/configure.html b/modules/hm_qc/templates/hm_qc/configure.html index 0d72397..fa63067 100644 --- a/modules/hm_qc/templates/hm_qc/configure.html +++ b/modules/hm_qc/templates/hm_qc/configure.html @@ -4,28 +4,39 @@ {% block content %}
Select a QC profile and customize settings
+Review settings and start execution
+