把这个菜单翻译为中文并保存原始布局
Erstellt am: 4. August 2026
Beantwortet mit GPT-5.6 Thinking von Chat01
Erstellt am: 4. August 2026
Beantwortet mit GPT-5.6 Thinking von Chat01
把这个菜单翻译为简体中文双语并保存原始布局,结果务必准确无误
pythonfrom PIL import Image img=Image.open('/mnt/data/IMG_6203.png') img.size (640, 405)
pythonfrom PIL import Image, ImageEnhance, ImageFilter img=Image.open('/mnt/data/IMG_6203.png') # right orig crop 370:640, 60:405 c=img.crop((360,60,640,405)).resize((1680,2070),Image.Resampling.LANCZOS) c=ImageEnhance.Contrast(c).enhance(1.5) c=ImageEnhance.Sharpness(c).enhance(2) c.save('/mnt/data/right_hi.png')
pythonfrom PIL import Image, ImageDraw, ImageFont, ImageEnhance from pathlib import Path src = Path("/mnt/data/IMG_6203.png") out = Path("/mnt/data/群来膳菜单_日中简体双语_原布局.png") # Upscale the supplied menu while keeping its original proportions and layout. base = Image.open(src).convert("RGB").resize((1920, 1215), Image.Resampling.LANCZOS) base = ImageEnhance.Sharpness(base).enhance(1.15) draw = ImageDraw.Draw(base) font_path = "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc" font_cn = ImageFont.truetype(font_path, 29) font_cn_small = ImageFont.truetype(font_path, 23) font_header = ImageFont.truetype(font_path, 32) font_footer = ImageFont.truetype(font_path, 22) translation_color = (137, 67, 38) # muted brown-red, distinct from the original Japanese header_color = (246, 234, 218) white = (255, 255, 255) def draw_vertical(text, x, y, font=font_cn, fill=translation_color, spacing=2, stroke_width=2, stroke_fill=white): """Draw simplified-Chinese text vertically, preserving the original Japanese beneath it.""" cy = y for ch in text: if ch == "\n": cy += font.size continue bbox = draw.textbbox((0, 0), ch, font=font, stroke_width=stroke_width) w = bbox[2] - bbox[0] h = bbox[3] - bbox[1] draw.text( (x - w / 2, cy), ch, font=font, fill=fill, stroke_width=stroke_width, stroke_fill=stroke_fill, ) cy += h + spacing # Header: keep the original Japanese title and add the simplified-Chinese equivalent. draw.text( (1260, 139), "群来膳菜单", font=font_header, fill=header_color, stroke_width=1, stroke_fill=(79, 34, 12), ) # Section labels. draw.text((765, 575), "卷寿司", font=font_cn_small, fill=translation_color, stroke_width=2, stroke_fill=white) draw.text((1710, 575), "握寿司", font=font_cn_small, fill=translation_color, stroke_width=2, stroke_fill=white) # Left section: Japanese remains untouched; Chinese is added beside each original column. left_items = [ (156, "干瓢卷"), (246, "紫苏牛蒡卷"), (336, "黄瓜卷"), (435, "腌萝卜卷"), (528, "梅子紫苏卷"), (615, "金枪鱼卷"), (705, "葱花金枪鱼泥卷"), (798, "金枪鱼腩卷"), ] for x, text in left_items: draw_vertical(text, x - 35, 300) # “二人前より” appears under the roll items; add one unobtrusive bilingual key. draw.text( (300, 1118), "(二人前より)= 两人份起", font=font_footer, fill=translation_color, stroke_width=2, stroke_fill=white, ) # Translate the vertical ordering note at the far left. draw_vertical( "※卷寿司也可按整卷单点,请告知店员。", 22, 455, font=font_cn_small, spacing=1, stroke_width=2, ) # Center boxed courses. draw_vertical("店主定制套餐", 1045, 292, font=font_cn_small, spacing=1) draw_vertical("河豚套餐\n需预约,至少提前三天", 980, 292, font=font_cn_small, spacing=1) # Right section. right_items = [ (1671, "群来膳特选握寿司"), (1587, "主厨精选握寿司"), (1497, "“华”握寿司"), (1410, "“雅”握寿司"), (1320, "北海道精选拼盘"), (1230, "贝类精选拼盘"), (1149, "炙烤金枪鱼腩握寿司(6贯)"), ] for x, text in right_items: draw_vertical(text, x - 37, 300) # Seasonal-content note for the two chef-selected sets. draw.text( (1450, 1118), "※内容会随季节调整", font=font_footer, fill=translation_color, stroke_width=2, stroke_fill=white, ) # Currency key: all original prices remain unchanged. draw.text( (838, 1172), "价格单位:日元(円)", font=font_footer, fill=translation_color, stroke_width=2, stroke_fill=white, ) base.save(out, quality=98) print(out)
pythonfrom PIL import Image, ImageDraw, ImageFont, ImageEnhance from pathlib import Path src = Path("/mnt/data/IMG_6203.png") out = Path("/mnt/data/群来膳菜单_日中简体双语_精准排版版.png") W, H = 2560, 1620 HEADER_H = 290 # Preserve the original header artwork; rebuild the body cleanly for exact bilingual typesetting. original = Image.open(src).convert("RGB") header = original.crop((0, 0, 640, 73)).resize((W, HEADER_H), Image.Resampling.LANCZOS) canvas = Image.new("RGB", (W, H), "white") canvas.paste(header, (0, 0)) draw = ImageDraw.Draw(canvas) font_path = "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc" jp_font = ImageFont.truetype(font_path, 44) cn_font = ImageFont.truetype(font_path, 29) small_jp = ImageFont.truetype(font_path, 24) small_cn = ImageFont.truetype(font_path, 22) price_font = ImageFont.truetype(font_path, 39) stamp_font = ImageFont.truetype(font_path, 92) header_cn = ImageFont.truetype(font_path, 34) note_font = ImageFont.truetype(font_path, 23) BLACK = (24, 18, 14) BROWN = (118, 55, 28) ORANGE = (228, 141, 94) HEADER_TEXT = (245, 233, 216) GRAY = (105, 95, 88) def vtext(text, x_center, y, font, fill, spacing=3): cy = y for ch in text: if ch == "\n": cy += font.size continue box = draw.textbbox((0, 0), ch, font=font) w = box[2] - box[0] h = box[3] - box[1] draw.text((x_center - w/2, cy), ch, font=font, fill=fill) cy += h + spacing return cy def dotted_line(x, y1, y2, gap=13, r=2): y = y1 while y <= y2: draw.ellipse((x-r, y-r, x+r, y+r), fill=(72, 63, 57)) y += gap def vertical_price(price, x, y): vtext(f"{price}円", x, y, price_font, BLACK, spacing=0) def stamp(x, y, char): size = 120 draw.rounded_rectangle((x, y, x+size, y+size), radius=8, outline=ORANGE, width=5) box = draw.textbbox((0, 0), char, font=stamp_font) tw, th = box[2]-box[0], box[3]-box[1] draw.text((x+(size-tw)/2, y+(size-th)/2-8), char, font=stamp_font, fill=ORANGE) # Bilingual header label. draw.text((1630, 165), "群来膳菜单", font=header_cn, fill=HEADER_TEXT) draw.text((1630, 115), "群来膳のメニュー", font=ImageFont.truetype(font_path, 29), fill=HEADER_TEXT) # Section stamps. stamp(1035, 330, "巻") stamp(2405, 330, "握") # Left-side note. vtext("※巻物は一本ずつでもご注文いただけます。", 35, 560, small_jp, BLACK, spacing=1) vtext("※卷寿司也可按整卷单点,请告知店员。", 67, 560, small_cn, BROWN, spacing=1) left_items = [ ("かんぴょう巻", "干瓢卷", "600"), ("しそごぼう巻", "紫苏牛蒡卷", "600"), ("かっぱ巻", "黄瓜卷", "600"), ("たくあん巻", "腌萝卜卷", "600"), ("うめしそ巻", "梅子紫苏卷", "900"), ("鉄火巻", "金枪鱼卷", "1,200"), ("ねぎとろ巻", "葱花金枪鱼泥卷", "2,400"), ("とろ鉄火巻", "金枪鱼腩卷", "2,400"), ] left_xs = [150, 270, 390, 510, 630, 750, 870, 990] for x, (jp, cn, price) in zip(left_xs, left_items): vtext(jp, x+19, 350, jp_font, BLACK, spacing=2) vtext(cn, x-24, 350, cn_font, BROWN, spacing=2) vtext("二人前より", x+17, 700, small_jp, GRAY, spacing=1) vtext("两人份起", x-24, 700, small_cn, BROWN, spacing=1) dotted_line(x, 885, 1265) vertical_price(price, x, 1292) # Center box. cx1, cy1, cx2, cy2 = 1165, 330, 1420, 1520 draw.rectangle((cx1, cy1, cx2, cy2), outline=(35, 30, 26), width=3) vtext("店主おまかせコース", 1355, 370, jp_font, BLACK, spacing=2) vtext("店主定制套餐", 1315, 370, cn_font, BROWN, spacing=2) vtext("季節により内容が変わります", 1375, 760, small_jp, GRAY, spacing=1) vtext("内容随季节调整", 1315, 810, small_cn, BROWN, spacing=1) dotted_line(1347, 1050, 1265) vertical_price("10,000", 1347, 1292) vtext("ふぐコース", 1225, 370, jp_font, BLACK, spacing=2) vtext("河豚套餐", 1190, 370, cn_font, BROWN, spacing=2) vtext("要予約・三日前から", 1235, 710, small_jp, GRAY, spacing=1) vtext("需预约・至少提前三天", 1190, 690, small_cn, BROWN, spacing=1) vtext("一人前", 1235, 1030, small_jp, GRAY, spacing=1) vtext("每位", 1190, 1030, small_cn, BROWN, spacing=1) dotted_line(1217, 1115, 1265) vertical_price("14,000", 1217, 1292) right_items = [ ("炙りとろ握", "炙烤金枪鱼腩握寿司", "3,600", "6カン", "6贯"), ("貝づくし", "贝类精选拼盘", "3,600", "", ""), ("北海づくし", "北海道精选拼盘", "3,700", "", ""), ("雅握", "“雅”握寿司", "2,200", "", ""), ("華握", "“华”握寿司", "3,200", "", ""), ("おまかせ握", "主厨精选握寿司", "4,500", "季節により内容が変わります", "内容随季节调整"), ("群来膳特選握", "群来膳特选握寿司", "6,000", "季節により内容が変わります", "内容随季节调整"), ] right_xs = [1510, 1650, 1790, 1930, 2070, 2210, 2350] for x, (jp, cn, price, jp_note, cn_note) in zip(right_xs, right_items): vtext(jp, x+22, 350, jp_font, BLACK, spacing=2) vtext(cn, x-24, 350, cn_font, BROWN, spacing=2) if jp_note: vtext(jp_note, x+22, 700, small_jp, GRAY, spacing=1) if cn_note: vtext(cn_note, x-24, 700, small_cn, BROWN, spacing=1) dotted_line(x, 890, 1265) vertical_price(price, x, 1292) # Footer. draw.text((1040, 1570), "价格单位:日元(円)", font=note_font, fill=BROWN) canvas.save(out, quality=98) print(out)
pythonfrom PIL import Image, ImageDraw, ImageFont from pathlib import Path src = Path("/mnt/data/IMG_6203.png") out = Path("/mnt/data/群来膳菜单_日中简体双语_最终版.png") W, H = 2560, 1620 HEADER_H = 290 original = Image.open(src).convert("RGB") header = original.crop((0, 0, 640, 73)).resize((W, HEADER_H), Image.Resampling.LANCZOS) canvas = Image.new("RGB", (W, H), "white") canvas.paste(header, (0, 0)) draw = ImageDraw.Draw(canvas) font_path = "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc" jp_font = ImageFont.truetype(font_path, 44) cn_font = ImageFont.truetype(font_path, 29) small_jp = ImageFont.truetype(font_path, 24) small_cn = ImageFont.truetype(font_path, 22) price_font = ImageFont.truetype(font_path, 39) stamp_font = ImageFont.truetype(font_path, 92) header_jp = ImageFont.truetype(font_path, 29) header_cn = ImageFont.truetype(font_path, 34) note_font = ImageFont.truetype(font_path, 23) center_jp = ImageFont.truetype(font_path, 34) center_cn = ImageFont.truetype(font_path, 23) BLACK = (24, 18, 14) BROWN = (118, 55, 28) ORANGE = (228, 141, 94) HEADER_TEXT = (245, 233, 216) GRAY = (105, 95, 88) HEADER_BROWN = (77, 31, 9) def vtext(text, x_center, y, font, fill, spacing=3): cy = y for ch in text: if ch == "\n": cy += font.size continue box = draw.textbbox((0, 0), ch, font=font) w = box[2] - box[0] h = box[3] - box[1] draw.text((x_center - w/2, cy), ch, font=font, fill=fill) cy += h + spacing return cy def dotted_line(x, y1, y2, gap=13, r=2): y = y1 while y <= y2: draw.ellipse((x-r, y-r, x+r, y+r), fill=(72, 63, 57)) y += gap def vertical_price(price, x, y): vtext(f"{price}円", x, y, price_font, BLACK, spacing=0) def stamp(x, y, char): size = 120 draw.rounded_rectangle((x, y, x+size, y+size), radius=8, outline=ORANGE, width=5) box = draw.textbbox((0, 0), char, font=stamp_font) tw, th = box[2]-box[0], box[3]-box[1] draw.text((x+(size-tw)/2, y+(size-th)/2-8), char, font=stamp_font, fill=ORANGE) # Clean the small header-title area and place the bilingual title without overlap. draw.rectangle((1550, 55, 2240, 225), fill=HEADER_BROWN) draw.text((1630, 80), "群来膳のメニュー", font=header_jp, fill=HEADER_TEXT) draw.text((1630, 142), "群来膳菜单", font=header_cn, fill=HEADER_TEXT) stamp(1035, 330, "巻") stamp(2405, 330, "握") vtext("※巻物は一本ずつでもご注文いただけます。", 35, 560, small_jp, BLACK, spacing=1) vtext("※卷寿司也可按整卷单点,请告知店员。", 67, 560, small_cn, BROWN, spacing=1) left_items = [ ("かんぴょう巻", "干瓢卷", "600"), ("しそごぼう巻", "紫苏牛蒡卷", "600"), ("かっぱ巻", "黄瓜卷", "600"), ("たくあん巻", "腌萝卜卷", "600"), ("うめしそ巻", "梅子紫苏卷", "900"), ("鉄火巻", "金枪鱼卷", "1,200"), ("ねぎとろ巻", "葱花金枪鱼泥卷", "2,400"), ("とろ鉄火巻", "金枪鱼腩卷", "2,400"), ] left_xs = [150, 270, 390, 510, 630, 750, 870, 990] for x, (jp, cn, price) in zip(left_xs, left_items): vtext(jp, x+19, 350, jp_font, BLACK, spacing=2) vtext(cn, x-24, 350, cn_font, BROWN, spacing=2) vtext("二人前より", x+17, 700, small_jp, GRAY, spacing=1) vtext("两人份起", x-24, 700, small_cn, BROWN, spacing=1) dotted_line(x, 885, 1265) vertical_price(price, x, 1292) # Center box with reduced typography to prevent collisions. cx1, cy1, cx2, cy2 = 1165, 330, 1420, 1520 draw.rectangle((cx1, cy1, cx2, cy2), outline=(35, 30, 26), width=3) vtext("店主おまかせコース", 1362, 370, center_jp, BLACK, spacing=1) vtext("店主定制套餐", 1314, 370, center_cn, BROWN, spacing=1) vtext("季節により内容が変わります", 1372, 760, small_jp, GRAY, spacing=1) vtext("内容随季节调整", 1314, 820, small_cn, BROWN, spacing=1) dotted_line(1347, 1050, 1265) vertical_price("10,000", 1347, 1292) vtext("ふぐコース", 1236, 370, center_jp, BLACK, spacing=1) vtext("河豚套餐", 1192, 370, center_cn, BROWN, spacing=1) vtext("要予約・三日前から", 1240, 710, small_jp, GRAY, spacing=1) vtext("需预约・至少提前三天", 1192, 690, small_cn, BROWN, spacing=1) vtext("一人前", 1240, 1030, small_jp, GRAY, spacing=1) vtext("每位", 1192, 1030, small_cn, BROWN, spacing=1) dotted_line(1217, 1115, 1265) vertical_price("14,000", 1217, 1292) right_items = [ ("炙りとろ握", "炙烤金枪鱼腩握寿司", "3,600", "6カン", "6贯"), ("貝づくし", "贝类精选拼盘", "3,600", "", ""), ("北海づくし", "北海道精选拼盘", "3,700", "", ""), ("雅握", "“雅”握寿司", "2,200", "", ""), ("華握", "“华”握寿司", "3,200", "", ""), ("おまかせ握", "主厨精选握寿司", "4,500", "季節により内容が変わります", "内容随季节调整"), ("群来膳特選握", "群来膳特选握寿司", "6,000", "季節により内容が変わります", "内容随季节调整"), ] right_xs = [1510, 1650, 1790, 1930, 2070, 2210, 2350] for x, (jp, cn, price, jp_note, cn_note) in zip(right_xs, right_items): vtext(jp, x+22, 350, jp_font, BLACK, spacing=2) vtext(cn, x-24, 350, cn_font, BROWN, spacing=2) if jp_note: vtext(jp_note, x+22, 700, small_jp, GRAY, spacing=1) if cn_note: vtext(cn_note, x-24, 700, small_cn, BROWN, spacing=1) dotted_line(x, 890, 1265) vertical_price(price, x, 1292) draw.text((1040, 1570), "价格单位:日元(円)", font=note_font, fill=BROWN) canvas.save(out, quality=98) print(out)
使用画图工具尽可能保持原始排版制作双语菜单
