U
    ui'                     @   s   d dl Z d dlZd dlmZmZmZmZ d dlZd dl	Z	d dl
Z
d dlmZ d dlmZmZmZmZmZ e  G dd dZe ZdS )    N)ImageImageEnhance	ImageDraw	ImageFont)datetime)r   r   r   r   ExifTagsc                	   @   s   e Zd Zdd ZeejdddZdejeeddd	Zd eje	e	ejdddZ
eje	edddZeje	ejdddZd!ejeejdddZd"eeee	eeedddZdS )#
ImageUtilsc                 C   sT   d| _ zdd l}|| _d| _ W n0 tk
rN   td ttjjd | _Y nX d S )NFr   TzSWarning: 'face_recognition' library not found. Falling back to OpenCV Haar Cascade.z#haarcascade_frontalface_default.xml)	use_face_recognition_libface_recognitionImportErrorprintcv2ZCascadeClassifierdataZhaarcascadesface_cascade)selfr
    r   (/home/lhs5088/backend/app/image_utils.py__init__   s    
zImageUtils.__init__)	file_pathreturnc              
   C   s   zt |}ztj D ]}tj| dkr q0q| }|dk	r||}|dkrb|jddd}n.|dkrz|jddd}n|d	kr|jd
dd}W n tk
r   Y nX |j	dkr|
d}|W S  tk
r } ztd| W 5 d}~X Y nX dS )z>Loads an image, handling HEIC conversion to RGB automatically.ZOrientationN      T)expand   i     Z   RGBzFailed to load image: )r   openr   ZTAGSkeys_getexifgetrotate	Exceptionmodeconvert
ValueError)r   r   imgZorientationexifer   r   r   
load_image   s,    



zImageUtils.load_image_   )r&   output_pathqualityc                 C   s   |j |d|d |S )z'Saves image to path, typically as JPEG.ZJPEG)r,   )save)r   r&   r+   r,   r   r   r   
save_image4   s    zImageUtils.save_image?ffffff?)r&   brightness_factorsharpness_factorr   c                 C   s,   t |}||}t |}||}|S )z%Applies basic auto-enhancement logic.)r   Z
BrightnessZenhanceZ	Sharpness)r   r&   r1   r2   Z
enhancer_bZ
enhancer_sr   r   r   auto_enhance9   s
    



zImageUtils.auto_enhance)r&   target_ratior   c                    s  |j \}}d}d ||kr>||  t|  }|||f}n|}t|}g }	| jrr| j|}
dd |
D }	nt	|tj
}| j|dd}	 dkr fdd|	D }	t|	dkrtd	d |	D t|	 }td
d |	D t|	 }n|d }|d }|| }||kr |}t|| }n|}t|| }||d  }||d  }|dk rVd}|dk rdd}|| |krz|| }|| |kr|| }t|t|t|| t|| fS )zv
        Calculates smart crop box focusing on faces.
        Optimized by resizing image for detection step.
        i   g      ?c                 S   s(   g | ] \}}}}|||| || fqS r   r   ).0toprightbottomleftr   r   r   
<listcomp>Y   s    
 z1ImageUtils.get_smart_crop_box.<locals>.<listcomp>g?   c                    s@   g | ]8\}}}}t |  t |  t |  t |  fqS r   )intr5   xywhscaler   r   r:   a   s    
 r   c                 S   s    g | ]\}}}}||d   qS    r   r=   r   r   r   r:   e   s    
 c                 S   s    g | ]\}}}}||d   qS rD   r   )r5   r>   r?   rA   r@   r   r   r   r:   f   s    
 rE   )sizer<   Zresizenparrayr	   r
   face_locationsr   ZcvtColorZCOLOR_RGB2GRAYr   ZdetectMultiScalelensum)r   r&   r4   original_widthoriginal_heightZdetect_widthZdetect_heightZimg_for_detectZcv_imgZfacesrI   grayZcenter_xZcenter_ycurrent_ratio
new_height	new_widthr9   r6   r   rB   r   get_smart_crop_boxA   sN    



 
   zImageUtils.get_smart_crop_boxc                 C   s   |j \}}|| }t|| dk r&|S ||kr@|}t|| }n|}t|| }td||fd}|| d }	|| d }
|||	|
f |S )z
        Adds white padding to the image to match the target ratio (Image Full).
        The image is NOT cropped; instead, white bars are added.
        g{Gz?r      rT   rT   rE   )rF   absr<   r   newZpaste)r   r&   r4   rL   rM   rO   rQ   rP   Znew_imgZpaste_xZpaste_yr   r   r   _add_white_padding   s    
zImageUtils._add_white_paddingN)r&   	date_textr   c                 C   sl  |sNz4|  }|r6|d}|r6t|d}|d}W n tk
rL   Y nX |sV|S t|}|j\}}t	|d }	zt
d|	}
W n tk
r   t
 }
Y nX z,|jd||
d\}}}}|| }|| }W n& tk
r   |j||
d\}}Y nX t	|d }t	|d }|| | }|| | }d	}d
}d
}|j|d |d f||
|d |j||f||
|d |S )z!Images date text on bottom right.i  z%Y:%m:%d %H:%M:%Sz%Y. %m. %d.gQ?z	arial.ttf)r   r   )fontg?)r   r   r   rS   rE   )rY   fill)r   r    r   strptimestrftimer"   r   ZDrawrF   r<   r   ZtruetypeIOErrorZload_defaultZtextbboxAttributeErrorZtextsizetext)r   r&   rX   r'   Zdate_strdtZdrawr@   rA   Z	font_sizerY   r9   r6   r7   r8   Ztext_wZtext_hZmargin_xZmargin_yr>   r?   Zshadow_colorZ
text_colorr   r   r   _draw_date_text   sF    


zImageUtils._draw_date_text
paper_fullUUUUUU?TF)
input_pathr+   	fill_modetarget_ratio_w_h
do_enhance
print_daterX   c           
      C   sl   |  |}|dkr*| ||}	||	}n|dkr>| ||}|rL| |}|r\| ||}| || |S )z'
        Main worker function.
        rb   
image_full)r)   rR   ZcroprW   r3   ra   r.   )
r   rd   r+   re   rf   rg   rh   rX   r&   Zcrop_boxr   r   r   process_and_save   s    

zImageUtils.process_and_save)r*   )r/   r0   )N)rb   rc   TFN)__name__
__module____qualname__r   strr   r)   r<   r.   floatr3   tuplerR   rW   ra   boolrj   r   r   r   r   r      s$   
D 9         r   )r   ZnumpyrG   ZPILr   r   r   r   Zpillow_heifosshutilr   r   Zregister_heif_openerr   image_utilsr   r   r   r   <module>   s    j