def _cnv_reduce(po_src_file, po_dst_file, po_cfg): """ Simple function to resize an image while respecting it's original aspect ratio. :param po_src_file: :param po_dst_file: :type po_cfg ImgConvertCfg: :return: """ # TODO: Think about something interesting to do with the options -o float,float # Variables preparation for imagemagick command # ---------------------------------------------- ti_img_src_size = _img_get_size(po_src_file.u_path) ti_img_dst_size = geom.max_rect_in(ptf_rec_out=po_cfg.ti_size, ptf_asp_in=po_cfg.tf_aspect) # Command line build #------------------- u_cmd = u'convert ' u_cmd += u'"%s" ' % cmd.sanitize_path(po_src_file.u_path) # Background u_cmd += u'-background "#%s" ' % po_cfg.u_color # Resize if ti_img_src_size[0] > ti_img_dst_size[0] and ti_img_src_size[1] > ti_img_dst_size[1]: u_cmd += u'-resize %ix%i! ' % (ti_img_dst_size[0], ti_img_dst_size[1]) # Rotation u_cmd += u'-rotate %f +repage ' % po_cfg.f_rotation # Final output u_cmd += u'"%s"' % cmd.sanitize_path(po_dst_file.u_path) # Command line execution #----------------------- du_output = cmd.execute(u_cmd) if du_output['u_stderr']: print du_output['u_stderr'] # Coordinates calculation after image manipulation #------------------------------------------------- o_img_transformation = ImgKeyCoords() o_img_transformation.ti_size = _img_get_size(po_dst_file.u_path) # Debug code to overlay image regions #_draw_coordinates(po_dst_file, o_img_transformation) return o_img_transformation
def _cnv_magcover(po_src_file, po_dst_file, po_cfg): """ :param po_src_file: :param po_dst_file: :param po_cfg: :return: """ # Media preparation #------------------ o_img_corner_fold = files.FilePath(o_MEDIA_ROOT_FP.u_path, u'magcover', u'corner_fold.png') o_img_corner_fold.absfile() u_img_corner_fold = o_img_corner_fold.u_path.decode('utf8') o_img_left_brightness = files.FilePath(o_MEDIA_ROOT_FP.u_path, u'magcover', u'left_brightness.png') o_img_left_brightness.absfile() u_img_left_brightness = o_img_left_brightness.u_path.decode('utf8') o_img_left_fold = files.FilePath(o_MEDIA_ROOT_FP.u_path, u'magcover', u'left_fold_dark.png') o_img_left_fold.absfile() u_img_left_fold = o_img_left_fold.u_path.decode('utf8') o_img_stp = files.FilePath(o_MEDIA_ROOT_FP.u_path, u'magcover', u'staple.png') o_img_stp.absfile() u_img_stp = o_img_stp.u_path.decode('utf8') # Trigonometric pre-calculations #------------------------------- f_sin = math.sin(math.radians(po_cfg.f_rotation)) f_cos = math.cos(math.radians(po_cfg.f_rotation)) # Variables preparation #---------------------- ti_cvr_size_final = geom.max_rect_in(po_cfg.ti_size, po_cfg.tf_aspect) # Staples ti_stp_size_orig = _img_get_size(u_img_stp) f_stp_pos_ratio = 0.049 * ti_cvr_size_final[0] / ti_cvr_size_final[1] + 0.220 # based in my quick statistical study f_stp_paper_y_ratio = 0.043 * 2 # TODO: Use statistical study again _i_stp_height = int(f_stp_paper_y_ratio * ti_cvr_size_final[1]) ti_stp_size_final = (int(1.0 * ti_stp_size_orig[0] * _i_stp_height / ti_stp_size_orig[1]), _i_stp_height) i_stp_x = int(11.0 / 60.0 * ti_stp_size_final[0]) # Landscape covers will have just one staple while portrait ones will have 2 li_staples_y = [] if float(ti_cvr_size_final[0]) / ti_cvr_size_final[1] > 1.0: li_staples_y.append(0.5 * ti_cvr_size_final[1] - 0.5 * _i_stp_height) else: li_staples_y.append(f_stp_pos_ratio * ti_cvr_size_final[1] - 0.5 * _i_stp_height) li_staples_y.append((1 - f_stp_pos_ratio) * ti_cvr_size_final[1] - 0.5 * _i_stp_height) # Left fold configuration i_fold_size = math.ceil(0.025 * ti_cvr_size_final[0]) f_fold_mult = 0.5 # Shadow configuration i_shadow1_dist = math.ceil(0.01 * min(po_cfg.ti_size)) i_shadow1_opac = 70 # 0-100 i_shadow1_blur = math.ceil(0.0025 * max(po_cfg.ti_size)) i_shadow2_blur = 4 * i_shadow1_blur # Left Brightness configuration f_left_bright_mult = 0.5 * (1 + abs(f_sin)) # 0.5 at 90º, 1.0 at 0º # Corner fold configuration f_bottom_right_bright_mult = 0.1 * (1 + max(0, math.cos(math.radians(45 + po_cfg.f_rotation)))) i_corner_fold_size_final = int(0.06 * ti_cvr_size_final[0]) # Command line build #------------------- u_cmd = u'convert ' u_cmd += u'"%s" ' % cmd.sanitize_path(po_src_file.u_path) # Source file u_cmd += u'-resize %ix%i! ' % (ti_cvr_size_final[0], ti_cvr_size_final[1]) # Resizing u_cmd += u'-background transparent ' # Transparent background # Left fold # TODO: Make left fold shadow transitions to a left fold brightness for high rotation angles (>45º) u_cmd += u'\( "%s" ' % u_img_left_fold u_cmd += u'-fill Black -colorize 100%%,100%%,100%%,0%% ' u_cmd += u'-resize %ix%i! ' % (i_fold_size, ti_cvr_size_final[1]) u_cmd += u'-channel alpha -fx "%s * a" ' % f_fold_mult # Alpha channel modification u_cmd += u'-gravity NorthWest -extent %ix0 ' % ti_cvr_size_final[0] u_cmd += u'-background "#808080" -flatten -background transparent ' u_cmd += u'\) -compose hardlight -composite ' # Left reflection # TODO: Make reflection intensity (and shape?) change with rotation angle. u_cmd += u'\( "%s" ' % cmd.sanitize_path(u_img_left_brightness) # Left brightness u_cmd += u'-resize %ix%i! ' % (ti_cvr_size_final[0], ti_cvr_size_final[1]) # Light add u_cmd += u'-channel alpha -fx "%s * a" ' % f_left_bright_mult # Alpha channel modification u_cmd += u'\) -composite ' # Bottom right corner fold reflection u_cmd += u'-gravity SouthEast ' u_cmd += u'\( "%s" ' % cmd.sanitize_path(u_img_corner_fold) u_cmd += u'-resize %ix%i! ' % (i_corner_fold_size_final, i_corner_fold_size_final) u_cmd += u'-channel alpha -fx "%s * a" ' % f_bottom_right_bright_mult u_cmd += u'\) -composite ' u_cmd += u'-gravity NorthWest ' # Staples u_cmd += u'-gravity east -extent +%i+0 -gravity northwest ' % i_stp_x for i_staple_y in li_staples_y: u_cmd += u'\( "%s" ' % cmd.sanitize_path(u_img_stp) u_cmd += u'-resize x%i ' % _i_stp_height u_cmd += u'-geometry +0+%i ' % i_staple_y u_cmd += u'\) -compose over -composite ' u_cmd += u'-rotate %f ' % po_cfg.f_rotation # Primary shadow u_cmd += u'\( ' u_cmd += u'-clone 0 -background black ' u_cmd += u'-resize 100%% ' u_cmd += u'-shadow %ix%i+0+%i ' % (i_shadow1_opac, i_shadow1_blur, i_shadow1_dist) u_cmd += u'\) ' # Secondary shadow u_cmd += u'\( ' u_cmd += u'-clone 0 -background black ' u_cmd += u'-shadow 40x%i+0+0 ' % i_shadow2_blur u_cmd += u'\) ' u_cmd += u'-reverse -background none -layers merge +repage ' # Shadow composition u_cmd += u'-background "#%s" -flatten ' % po_cfg.u_color # Background color u_cmd += u'"%s"' % cmd.sanitize_path(po_dst_file.u_path) # Output file # Command line execution #----------------------- du_output = cmd.execute(u_cmd) if du_output['u_stderr']: print du_output['u_stderr'] # Transformation object result ti_final_size = _img_get_size(po_dst_file.u_path) i_extra_top = max(0, i_shadow1_blur - i_shadow1_dist, i_shadow2_blur) i_extra_bottom = max(0, i_shadow1_blur + i_shadow1_dist, i_shadow2_blur) # Delta distances in rotated image in screen coordinates tf_dx = (0.5 * f_cos * ti_cvr_size_final[0], -0.5 * f_sin * ti_cvr_size_final[0]) tf_dy = (-0.5 * f_sin * ti_cvr_size_final[1], -0.5 * f_cos * ti_cvr_size_final[1]) tf_center = (0.5 * ti_final_size[0] + i_stp_x * f_cos, 0.5 * (ti_final_size[1] - i_extra_top - i_extra_bottom) + i_extra_top) tf_left = (tf_center[0] - tf_dx[0], tf_center[1] - tf_dx[1]) tf_right = (tf_center[0] + tf_dx[0], tf_center[1] + tf_dx[1]) tf_top = (tf_center[0] + tf_dy[0], tf_center[1] + tf_dy[1]) tf_top_left = (tf_top[0] - tf_dx[0], tf_top[1] - tf_dx[1]) tf_top_right = (tf_top[0] + tf_dx[0], tf_top[1] + tf_dx[1]) tf_bottom = (tf_center[0] - tf_dy[0], tf_center[1] - tf_dy[1]) tf_bottom_left = (tf_bottom[0] - tf_dx[0], tf_bottom[1] - tf_dx[1]) tf_bottom_right = (tf_bottom[0] + tf_dx[0], tf_bottom[1] + tf_dx[1]) # Transformation object result o_img_transformation = ImgKeyCoords() o_img_transformation.ti_size = ti_final_size o_img_transformation.tf_top_left = (tf_top_left[0] / ti_final_size[0], tf_top_left[1] / ti_final_size[1]) o_img_transformation.tf_top = (tf_top[0] / ti_final_size[0], tf_top[1] / ti_final_size[1]) o_img_transformation.tf_top_right = (tf_top_right[0] / ti_final_size[0], tf_top_right[1] / ti_final_size[1]) o_img_transformation.tf_left = (tf_left[0] / ti_final_size[0], tf_left[1] / ti_final_size[1]) o_img_transformation.tf_center = (tf_center[0] / ti_final_size[0], tf_center[1] / ti_final_size[1]) o_img_transformation.tf_right = (tf_right[0] / ti_final_size[0], tf_right[1] / ti_final_size[1]) o_img_transformation.tf_bottom_left = (tf_bottom_left[0] / ti_final_size[0], tf_bottom_left[1] / ti_final_size[1]) o_img_transformation.tf_bottom = (tf_bottom[0] / ti_final_size[0], tf_bottom[1] / ti_final_size[1]) o_img_transformation.tf_bottom_right = (tf_bottom_right[0] / ti_final_size[0], tf_bottom_right[1] / ti_final_size[1]) # Debug code to overlay image regions #_draw_coordinates(po_dst_file, o_img_transformation) return o_img_transformation
def _cnv_frame(po_src_file, po_dst_file, po_cfg): """ Image conversion that adds a picture frame around the image and soft reflections. Focus point is used to set the center of the reflection image. :param po_src_file: Input file. i.e. '/home/john/original_picture.jpg' :param po_dst_file: Output file. i.e. '/home/john/modified_picture.png' :param po_cfg: Configuration object. See hq_img_convert to see :return: An ImgKeyCoords object containing the relative coordinates (0.0-1.0) of 9 key positions (top-left, top, top-right, left, center, right, bottom-left, bottom, bottom-right. """ # Media preparation #------------------ o_img_light = files.FilePath(o_MEDIA_ROOT_FP.u_path, u'frame', u'brightness.png') o_img_light.absfile() # Variables preparation for imagemagick command #---------------------------------------------- ti_img_size = geom.max_rect_in(ptf_rec_out=po_cfg.ti_size, ptf_asp_in=po_cfg.tf_aspect) i_light_size = 2 * max(ti_img_size[0], ti_img_size[1]) f_aspect_ratio = po_cfg.tf_aspect[0] / po_cfg.tf_aspect[1] f_gb_aspect_ratio = 160.0 / 144.0 # Real location (x,y) in pixels of the focus point of the image ti_focus = (int(po_cfg.tf_options[0] * ti_img_size[0]), int(po_cfg.tf_options[1] * ti_img_size[1])) # Then, the offsets are calculated to make the center of the light image fall over that point. Imagemagick format # for offsets in geometry is +x+y when moving the top-left corner of the overlay image x pixels to the right and y # pixels to the bottom. ti_foc_img_off = (- 0.5 * i_light_size + ti_focus[0], - 0.5 * i_light_size + ti_focus[1]) if ti_foc_img_off[0] >= 0: u_foc_img_extra_x = u'+' else: u_foc_img_extra_x = u'' if ti_foc_img_off[1] >= 0: u_foc_img_extra_y = u'+' else: u_foc_img_extra_y = u'' u_foc_img_off = u'%s%i%s%i' % (u_foc_img_extra_x, ti_foc_img_off[0], u_foc_img_extra_y, ti_foc_img_off[1]) # Frame configuration i_frame_thickness = math.ceil(0.03 * min(po_cfg.ti_size)) u_frame_color = u'#f0f0f0' ti_frame_size = (ti_img_size[0] + 2 * i_frame_thickness, ti_img_size[1] + 2 * i_frame_thickness) # Shadow configuration i_shadow_dist = math.ceil(0.005 * min(po_cfg.ti_size)) i_shadow_opac = 60 # 0-100 i_shadow_blur = math.ceil(0.0025 * max(po_cfg.ti_size)) # Sin and Cos of the rotation are going to be used several times so I pre-calculate them to make the script a bit # faster. f_sin = math.sin(math.radians(po_cfg.f_rotation)) f_cos = math.cos(math.radians(po_cfg.f_rotation)) # Number of image colors to colorize gameboy screenshots i_colors = _img_count_colors(po_src_file.u_path) b_grayscale = _img_is_grayscale(po_src_file.u_path) # Command line build #------------------- u_cmd = u'convert ' u_cmd += u'"%s" ' % cmd.sanitize_path(po_src_file.u_path) # Source file if f_aspect_ratio == f_gb_aspect_ratio and i_colors <= 4 and b_grayscale: # GameBoy (mono) color tint u_cmd += u'+level-colors "#0f380e,#9bbb0e" ' #else: # print po_src_file.u_path # print 'aspect: %f (!= %f)' % (f_aspect_ratio, f_gb_aspect_ratio) # print 'colors: %i' % i_colors # print ' b/w: %s' % b_grayscale u_cmd += u'-resize %ix%i! ' % (ti_img_size[0], ti_img_size[1]) # Resizing u_cmd += u'-background transparent ' # Transparent background u_cmd += u'\( "%s" -resize %ix%i! -geometry %s \) -composite ' % (cmd.sanitize_path(o_img_light.u_path), i_light_size, i_light_size, u_foc_img_off) # Light/shadow add u_cmd += u'-bordercolor "%s" -border %i ' % (u_frame_color, i_frame_thickness) # Frame border u_cmd += u'-rotate %f ' % po_cfg.f_rotation # Rotation u_cmd += u'\( -clone 0 -background black -shadow %ix%i+0+%i \) ' % (i_shadow_opac, i_shadow_blur, i_shadow_dist) # Shadow creation u_cmd += u'-reverse -background none -layers merge +repage ' # Shadow composition u_cmd += u'-background "#%s" -flatten ' % po_cfg.u_color # Background color u_cmd += u'"%s"' % cmd.sanitize_path(po_dst_file.u_path) # Output file # Command line execution #----------------------- du_output = cmd.execute(u_cmd) if du_output['u_stderr']: print du_output['u_stderr'] # Coordinates calculation after image manipulation #------------------------------------------------- ti_img_size = _img_get_size(po_dst_file.u_path) i_extra_top = max(0, i_shadow_blur - i_shadow_dist) i_extra_bottom = max(0, i_shadow_blur + i_shadow_dist) # Delta distances in rotated image in screen coordinates tf_dx = (0.5 * ti_frame_size[0] * f_cos, 0.5 * ti_frame_size[0] * f_sin) tf_dy = (0.5 * ti_frame_size[1] * f_sin, 0.5 * ti_frame_size[1] * f_cos) # Absolute offsets of image key-positions tf_center = (0.5 * ti_img_size[0], 0.5 * (ti_img_size[1] - i_extra_top - i_extra_bottom) + i_extra_top) tf_left = (tf_center[0] - tf_dx[0], tf_center[1] + tf_dx[1]) tf_right = (tf_center[0] + tf_dx[0], tf_center[1] - tf_dx[1]) tf_bottom = (tf_center[0] + tf_dy[0], tf_center[1] + tf_dy[1]) tf_bottom_left = (tf_bottom[0] - tf_dx[0], tf_bottom[1] + tf_dx[1]) tf_bottom_right = (tf_bottom[0] + tf_dx[0], tf_bottom[1] - tf_dx[1]) tf_top = (tf_center[0] - tf_dy[0], tf_center[1] - tf_dy[1]) tf_top_left = (tf_top[0] - tf_dx[0], tf_top[1] + tf_dx[1]) tf_top_right = (tf_top[0] + tf_dx[0], tf_top[1] - tf_dx[1]) # Transformation object result o_img_transformation = ImgKeyCoords() o_img_transformation.ti_size = ti_img_size o_img_transformation.tf_top_left = (tf_top_left[0] / ti_img_size[0], tf_top_left[1] / ti_img_size[1]) o_img_transformation.tf_top = (tf_top[0] / ti_img_size[0], tf_top[1] / ti_img_size[1]) o_img_transformation.tf_top_right = (tf_top_right[0] / ti_img_size[0], tf_top_right[1] / ti_img_size[1]) o_img_transformation.tf_left = (tf_left[0] / ti_img_size[0], tf_left[1] / ti_img_size[1]) o_img_transformation.tf_center = (tf_center[0] / ti_img_size[0], tf_center[1] / ti_img_size[1]) o_img_transformation.tf_right = (tf_right[0] / ti_img_size[0], tf_right[1] / ti_img_size[1]) o_img_transformation.tf_bottom_left = (tf_bottom_left[0] / ti_img_size[0], tf_bottom_left[1] / ti_img_size[1]) o_img_transformation.tf_bottom = (tf_bottom[0] / ti_img_size[0], tf_bottom[1] / ti_img_size[1]) o_img_transformation.tf_bottom_right = (tf_bottom_right[0] / ti_img_size[0], tf_bottom_right[1] / ti_img_size[1]) # Debug code to overlay image regions # draw_coordinates(po_dst_file, o_img_transformation) return o_img_transformation