Created
May 12, 2026 09:27
-
-
Save nna774/3a21e1dcd15276e3f3c60735f3ebc176 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| CMYKテストパターン生成スクリプト | |
| - output_no_profile.jpg : ICCプロファイルなし(Twitterが誤変換するやつ) | |
| - output_with_profile.jpg: ICCプロファイルあり(正しく変換された場合) | |
| """ | |
| from PIL import Image, ImageDraw, ImageFont | |
| import struct | |
| W, H = 800, 1000 | |
| def make_cmyk_image(): | |
| img = Image.new("CMYK", (W, H), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| # --- 各チャンネル単色スウォッチ --- | |
| swatches = [ | |
| ((255, 0, 0, 0 ), "C=100"), | |
| ((0, 255, 0, 0 ), "M=100"), | |
| ((0, 0, 255, 0 ), "Y=100"), | |
| ((0, 0, 0, 255), "K=100"), | |
| ((0, 255, 255, 0 ), "M+Y (赤系)"), | |
| ((255, 0, 255, 0 ), "C+Y (緑系)"), | |
| ((255, 255, 0, 0 ), "C+M (青系)"), | |
| ] | |
| sw_w = W // len(swatches) | |
| for i, (color, label) in enumerate(swatches): | |
| x0 = i * sw_w | |
| draw.rectangle([x0, 0, x0 + sw_w, 80], fill=color) | |
| # ラベルは白で(K=0なので背景に対して見える) | |
| draw.text((x0 + 4, 58), label, fill=(0, 0, 0, 200)) | |
| # --- Mチャンネル単独グラデーション --- | |
| draw.text((10, 90), "M channel gradient (C=0,Y=0,K=0)", fill=(0, 0, 0, 200)) | |
| for x in range(W): | |
| m = int(x / W * 255) | |
| draw.line([(x, 110), (x, 170)], fill=(0, m, 0, 0)) | |
| # --- 肌色グラデーション(C低め、M/Y高め)--- | |
| draw.text((10, 180), "Skin tone gradient (C=5, M=20->60, Y=25->50, K=0)", fill=(0, 0, 0, 200)) | |
| steps = W | |
| for x in range(steps): | |
| t = x / steps | |
| c = 5 | |
| m = int(20 + t * 40) # 20→60 | |
| y = int(25 + t * 25) # 25→50 | |
| k = 0 | |
| draw.line([(x, 200), (x, 260)], fill=(c, m, y, k)) | |
| # --- Kのみグレースケール --- | |
| draw.text((10, 270), "K-only grayscale (C=M=Y=0)", fill=(0, 0, 0, 200)) | |
| for x in range(W): | |
| k = int(x / W * 255) | |
| draw.line([(x, 290), (x, 350)], fill=(0, 0, 0, k)) | |
| # --- シャドウ肌色(Kあり)--- | |
| draw.text((10, 360), "Shadow skin (C=10, M=40, Y=30, K=0->50)", fill=(0, 0, 0, 200)) | |
| for x in range(W): | |
| t = x / W | |
| k = int(t * 128) | |
| draw.line([(x, 380), (x, 440)], fill=(26, 102, 77, k)) | |
| # --- CMYKスウォッチグリッド(細かい値)--- | |
| draw.text((10, 450), "CMYK swatches (肌色系)", fill=(0, 0, 0, 200)) | |
| skin_tones = [ | |
| (5, 15, 20, 0, "薄い肌"), | |
| (5, 25, 30, 0, "標準肌"), | |
| (5, 35, 40, 0, "濃い肌"), | |
| (10, 40, 35, 10, "影肌1"), | |
| (10, 50, 40, 20, "影肌2"), | |
| (0, 60, 50, 0, "赤み肌"), | |
| (0, 80, 60, 0, "強赤み"), | |
| ] | |
| sw_w2 = W // len(skin_tones) | |
| for i, (c, m, y, k, label) in enumerate(skin_tones): | |
| x0 = i * sw_w2 | |
| draw.rectangle([x0, 470, x0 + sw_w2, 560], fill=( | |
| int(c/100*255), int(m/100*255), int(y/100*255), int(k/100*255) | |
| )) | |
| draw.text((x0 + 4, 538), label, fill=(0, 0, 0, 200)) | |
| # --- 全チャンネル段階グリッド(M vs Y)--- | |
| draw.text((10, 570), "M(縦) vs Y(横) grid, C=5, K=0", fill=(0, 0, 0, 200)) | |
| grid_steps = 8 | |
| cell_w = W // grid_steps | |
| cell_h = 40 | |
| for row in range(grid_steps): | |
| for col in range(grid_steps): | |
| m = int(row / (grid_steps - 1) * 200) | |
| y = int(col / (grid_steps - 1) * 200) | |
| x0 = col * cell_w | |
| y0 = 590 + row * cell_h | |
| draw.rectangle([x0, y0, x0 + cell_w, y0 + cell_h], | |
| fill=(13, m, y, 0)) | |
| # --- 白・グレー確認用 --- | |
| draw.text((10, 920), "White / near-white check", fill=(0, 0, 0, 200)) | |
| whites = [ | |
| ((0, 0, 0, 0), "Pure White\nC0M0Y0K0"), | |
| ((5, 5, 5, 0), "Near white\nC5M5Y5K0"), | |
| ((0, 5, 5, 0), "Warm white\nC0M5Y5K0"), | |
| ((5, 0, 0, 0), "Cool white\nC5M0Y0K0"), | |
| ((0, 0, 0, 10), "Light gray\nK10"), | |
| ((0, 0, 0, 30), "Gray K30"), | |
| ] | |
| sw_w3 = W // len(whites) | |
| for i, (color, label) in enumerate(whites): | |
| x0 = i * sw_w3 | |
| draw.rectangle([x0, 940, x0 + sw_w3, H], fill=color) | |
| draw.text((x0 + 4, H - 52), label, fill=(0, 0, 0, 180)) | |
| return img | |
| img = make_cmyk_image() | |
| # 1) ICCプロファイルなしで保存 | |
| img.save("/tmp/cmyk_test/output_no_profile.jpg", format="JPEG") | |
| print("saved: output_no_profile.jpg") | |
| # 2) ICCプロファイルあり(JapanColor2001Coated相当のプロファイルがない場合は | |
| # sRGB変換してから保存するのが「正しく見える」側の代替) | |
| rgb_img = img.convert("RGB") | |
| rgb_img.save("/tmp/cmyk_test/output_rgb_converted.jpg", format="JPEG") | |
| print("saved: output_rgb_converted.jpg (CMYK→RGB正変換済み)") | |
| print("\n比較方法:") | |
| print(" output_no_profile.jpg → Twitterにそのままアップ → 誤変換後の色") | |
| print(" output_rgb_converted.jpg → 正しく変換した場合の色") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment