Adjust Wolf for Ruins and improve images
This commit is contained in:
parent
d2005637d6
commit
fdac11eaef
4 changed files with 179 additions and 62 deletions
|
|
@ -81,24 +81,23 @@ def handleImages(folderName, estimate):
|
|||
translatedData = openFiles(f"files/{folderName}")
|
||||
|
||||
# Custom Names
|
||||
customList = [[], []]
|
||||
customList = processImagesDir("Custom", customList)
|
||||
# customList = [[], []]
|
||||
# customList = processImagesDir("Custom", customList)
|
||||
|
||||
# Write Strings to Images
|
||||
if not ESTIMATE:
|
||||
if not os.path.exists(f"translated/{folderName}"):
|
||||
os.mkdir(f"translated/{folderName}")
|
||||
for i in range(len(translatedData[0][0])):
|
||||
# Write TL To Images
|
||||
try:
|
||||
translatedList, originalList, dimensionsList = translatedData[0]
|
||||
for i in range(len(translatedList)):
|
||||
try:
|
||||
translatedList = translatedData[0][0]
|
||||
originalList = translatedData[0][1]
|
||||
dimensionsList = translatedData[0][2]
|
||||
image = stringToImage(translatedList[i], dimensionsList[i][0], dimensionsList[i][1])
|
||||
image.save(rf"translated/{folderName}/{customList[0][0]}.png", quality=100)
|
||||
customList[0].pop(0)
|
||||
# Create image from string
|
||||
image = stringToImageOutline(translatedList[i], dimensionsList[i][0], dimensionsList[i][1])
|
||||
# Save image using the corresponding original filename
|
||||
image.save(rf"translated/{folderName}/{originalList[i]}.png", quality=100)
|
||||
except Exception as e:
|
||||
PBAR.write(f"{translatedList[i]}: {str(e)}")
|
||||
# Ignore Error
|
||||
# Log error if image saving fails
|
||||
PBAR.write(f"Error processing {translatedList[i]}: {str(e)}")
|
||||
except IndexError:
|
||||
PBAR.write("Translated data is incomplete. Please check your input.")
|
||||
|
||||
# Print File
|
||||
end = time.time()
|
||||
|
|
@ -121,7 +120,7 @@ def openFiles(folderName):
|
|||
global PBAR
|
||||
|
||||
if os.path.isdir(folderName):
|
||||
imageList = [[], []]
|
||||
imageList = [[], [], []]
|
||||
imageList = processImagesDir(folderName, imageList)
|
||||
|
||||
# Start Translation
|
||||
|
|
@ -134,7 +133,7 @@ def openFiles(folderName):
|
|||
) as PBAR:
|
||||
translatedData = translateImages(imageList)
|
||||
translatedData = [
|
||||
[translatedData[0], imageList[0], imageList[1]],
|
||||
[translatedData[0], imageList[2], imageList[1]],
|
||||
translatedData[1],
|
||||
translatedData[2],
|
||||
]
|
||||
|
|
@ -209,6 +208,8 @@ def stringToImage(text, width, height, font_path="fonts/TsunagiGothic.ttf", scal
|
|||
text_width = text_bbox[2] - text_bbox[0]
|
||||
text_height = text_bbox[3] - text_bbox[1] + 20
|
||||
x = 0
|
||||
|
||||
x = (scaled_width - text_width) // 2
|
||||
y = (scaled_height - text_height) // 2
|
||||
|
||||
# Draw the text on the image
|
||||
|
|
@ -222,6 +223,110 @@ def stringToImage(text, width, height, font_path="fonts/TsunagiGothic.ttf", scal
|
|||
|
||||
return image
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
def stringToImageOutline(text, width, height, font_path="fonts/TsunagiGothic.ttf", scale_factor=4):
|
||||
# Outline
|
||||
outline_color=(0, 0, 0, 255)
|
||||
outline_thickness=4
|
||||
|
||||
# Increase the resolution
|
||||
scaled_width = int(width * scale_factor)
|
||||
scaled_height = int(height * scale_factor)
|
||||
|
||||
# Find the appropriate font size for the scaled up image
|
||||
font_size = getFontSize(text, scaled_width, scaled_height, font_path)
|
||||
if font_size == 0:
|
||||
raise ValueError("Text is too long to fit in the supplied dimensions.")
|
||||
|
||||
# Create a new image with the scaled width and height and a transparent background
|
||||
image = Image.new("RGBA", (scaled_width, scaled_height), (255, 255, 255, 0))
|
||||
|
||||
# Create a drawing context
|
||||
draw = ImageDraw.Draw(image)
|
||||
|
||||
# Load the appropriate font
|
||||
font = ImageFont.truetype(font_path, font_size)
|
||||
|
||||
# Calculate the size of the text to center it
|
||||
text_bbox = draw.textbbox((0, 0), text, font=font)
|
||||
text_width = text_bbox[2] - text_bbox[0]
|
||||
text_height = text_bbox[3] - text_bbox[1] + 20
|
||||
x = (scaled_width - text_width) // 2
|
||||
y = (scaled_height - text_height) // 2
|
||||
|
||||
# Draw the text outline by applying the text multiple times with small offsets
|
||||
for dx in range(-outline_thickness, outline_thickness + 1):
|
||||
for dy in range(-outline_thickness, outline_thickness + 1):
|
||||
if dx != 0 or dy != 0:
|
||||
draw.text((x + dx, y + dy), text, font=font, fill=outline_color)
|
||||
|
||||
# Draw the main text
|
||||
draw.text((x, y), text, font=font, fill=(60, 160, 230, 255))
|
||||
|
||||
# Resize back to the original dimensions to get a clearer text rendering
|
||||
image = image.resize((width, height), Image.LANCZOS)
|
||||
|
||||
return image
|
||||
|
||||
def stringToImageBox(text, width, height, font_path="fonts/TsunagiGothic.ttf", scale_factor=4):
|
||||
# Increase the resolution
|
||||
scaled_width = int(width * scale_factor)
|
||||
scaled_height = int(height * scale_factor)
|
||||
|
||||
# Padding around the text
|
||||
padding = 10
|
||||
|
||||
# Calculate the dimensions available for text placement
|
||||
available_width = scaled_width - 2 * padding
|
||||
available_height = scaled_height - 2 * padding
|
||||
|
||||
# Determine the best font size to fit within the available dimensions
|
||||
font_size = getFontSize(text, available_width, available_height, font_path)
|
||||
if font_size <= 0:
|
||||
raise ValueError("Text is too long to fit in the supplied dimensions.")
|
||||
|
||||
# Create a new image with increased resolution
|
||||
image = Image.new("RGBA", (scaled_width, scaled_height), (255, 255, 255, 0))
|
||||
draw = ImageDraw.Draw(image)
|
||||
|
||||
# Load the calculated font
|
||||
font = ImageFont.truetype(font_path, font_size)
|
||||
|
||||
# Calculate the size and bounding box of the text
|
||||
text_bbox = draw.textbbox((0, 0), text, font=font)
|
||||
text_width = text_bbox[2] - text_bbox[0]
|
||||
text_height = text_bbox[3] - text_bbox[1] + 20
|
||||
|
||||
# Determine centered position for the text while considering padding
|
||||
# Additional adjustment ensures text appears centrally aligned
|
||||
x = (scaled_width - text_width) // 2
|
||||
y = (scaled_height - text_height) // 2
|
||||
|
||||
# Draw a black box with a white outline that fits the image dimensions precisely
|
||||
draw.rectangle(
|
||||
[0, 0, scaled_width - 1, scaled_height - 1],
|
||||
outline=(255, 255, 255, 255),
|
||||
width=1
|
||||
)
|
||||
|
||||
# Fill the inside box with black color
|
||||
draw.rectangle(
|
||||
[1, 1, scaled_width - 2, scaled_height - 2],
|
||||
fill=(0, 0, 0, 255)
|
||||
)
|
||||
|
||||
# Render the text within the image
|
||||
draw.text((x, y), text, font=font, fill=(255, 255, 255, 255))
|
||||
|
||||
# Shrink the image back to original dimensions with high-quality interpolation
|
||||
image = image.resize(
|
||||
(width, height),
|
||||
Image.LANCZOS,
|
||||
)
|
||||
|
||||
return image
|
||||
|
||||
|
||||
def getImageDimensions(file_path):
|
||||
try:
|
||||
|
|
@ -248,8 +353,14 @@ def processImagesDir(directory_path, imageList):
|
|||
}
|
||||
for target, replacement in placeholders.items():
|
||||
file_name = file_name.replace(target, replacement)
|
||||
imageList[0].append(file_name)
|
||||
match = re.search(r"[\[【].+?[\]】](.*)", file_name)
|
||||
if match:
|
||||
text = match.group(1)
|
||||
else:
|
||||
text = file_name
|
||||
imageList[0].append(text)
|
||||
imageList[1].append([width, height])
|
||||
imageList[2].append(file_name)
|
||||
except Exception as e:
|
||||
print(f"Error processing {file_name}: {e}")
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ def handleMVMZ(filename, estimate):
|
|||
|
||||
|
||||
def openFiles(filename):
|
||||
with open("files/" + filename, "r", encoding="utf-8-sig") as f:
|
||||
with open("files/" + filename, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Map Files
|
||||
|
|
@ -1314,7 +1314,7 @@ def searchCodes(page, pbar, jobList, filename):
|
|||
for key, (argVar, font) in headerMappings.items():
|
||||
if key in headerString:
|
||||
translatePlugins(argVar, font)
|
||||
|
||||
|
||||
if headerString == "LL_GalgeChoiceWindow":
|
||||
### Message Text First
|
||||
jaString = codeList[i]["parameters"][3]["messageText"]
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@ PBAR = None
|
|||
FILENAME = None
|
||||
|
||||
# Dialogue / Choices
|
||||
CODE101 = False
|
||||
CODE102 = False
|
||||
CODE101 = True
|
||||
CODE102 = True
|
||||
|
||||
# Set String (Fragile but necessary)
|
||||
CODE122 = False
|
||||
|
|
@ -301,56 +301,56 @@ def searchCodes(events, pbar, jobList, filename):
|
|||
if codeList[i]["code"] == 101 and CODE101 == True:
|
||||
# Grab String
|
||||
jaString = codeList[i]["stringArgs"][0]
|
||||
initialJAString = jaString
|
||||
speaker = ""
|
||||
|
||||
# Grab Speaker
|
||||
if ":\n" in jaString:
|
||||
nameList = re.findall(r"(.*):\n", jaString)
|
||||
if nameList is not None:
|
||||
match = re.search(r"@\d+\n(.*):\n", jaString)
|
||||
if match:
|
||||
# TL Speaker
|
||||
response = getSpeaker(nameList[0])
|
||||
response = getSpeaker(match.group(1))
|
||||
speaker = response[0]
|
||||
totalTokens[0] += response[1][0]
|
||||
totalTokens[1] += response[1][1]
|
||||
|
||||
# Set nametag and remove from string
|
||||
nametag = f"{speaker}:\n"
|
||||
jaString = jaString.replace(f"{nameList[0]}:\n", "")
|
||||
codeList[i]["stringArgs"][0] = codeList[i]["stringArgs"][0].replace(match.group(1), speaker)
|
||||
|
||||
# Grab Only Text
|
||||
match = re.search(r"\n\s+([\w\W\n]+)", codeList[i]["stringArgs"][0])
|
||||
if match:
|
||||
jaString = match.group(1)
|
||||
initialJAString = jaString
|
||||
|
||||
# Remove Textwrap
|
||||
jaString = jaString.replace("\n", " ")
|
||||
# Remove Textwrap
|
||||
jaString = jaString.replace("\n", " ")
|
||||
|
||||
# 1st Pass (Save Text to List)
|
||||
if not setData:
|
||||
if speaker == "":
|
||||
stringList.append(jaString)
|
||||
# 1st Pass (Save Text to List)
|
||||
if not setData:
|
||||
if speaker == "":
|
||||
stringList.append(jaString)
|
||||
else:
|
||||
stringList.append(f"[{speaker}]: {jaString}")
|
||||
|
||||
# 2nd Pass (Set Text)
|
||||
else:
|
||||
stringList.append(f"[{speaker}]: {jaString}")
|
||||
# Grab Translated String
|
||||
translatedText = stringList[0]
|
||||
|
||||
# 2nd Pass (Set Text)
|
||||
else:
|
||||
# Grab Translated String
|
||||
translatedText = stringList[0]
|
||||
# Remove speaker
|
||||
matchSpeakerList = re.findall(r"^(\[.+?\]\s?[|:]\s?)\s?", translatedText)
|
||||
if len(matchSpeakerList) > 0:
|
||||
translatedText = translatedText.replace(matchSpeakerList[0], "")
|
||||
|
||||
# Remove speaker
|
||||
matchSpeakerList = re.findall(r"^(\[.+?\]\s?[|:]\s?)\s?", translatedText)
|
||||
if len(matchSpeakerList) > 0:
|
||||
translatedText = translatedText.replace(matchSpeakerList[0], "")
|
||||
# Textwrap
|
||||
if FIXTEXTWRAP is True:
|
||||
translatedText = textwrap.fill(translatedText, width=WIDTH)
|
||||
|
||||
# Textwrap
|
||||
if FIXTEXTWRAP is True:
|
||||
translatedText = textwrap.fill(translatedText, width=WIDTH)
|
||||
# Set Data
|
||||
codeList[i]["stringArgs"][0] = codeList[i]["stringArgs"][0].replace(initialJAString, translatedText)
|
||||
|
||||
# Add back Nametag
|
||||
translatedText = nametag + translatedText
|
||||
nametag = ""
|
||||
|
||||
# Set Data
|
||||
codeList[i]["stringArgs"][0] = translatedText
|
||||
|
||||
# Reset Data and Pop Item
|
||||
speaker = ""
|
||||
stringList.pop(0)
|
||||
# Reset Data and Pop Item
|
||||
stringList.pop(0)
|
||||
|
||||
### Event Code: 102 Choices
|
||||
if codeList[i]["code"] == 102 and CODE102 == True:
|
||||
|
|
|
|||
18
vocab.txt
18
vocab.txt
|
|
@ -1,12 +1,18 @@
|
|||
Here are some vocabulary and terms so that you know the proper spelling and translation.
|
||||
```
|
||||
# Game Characters
|
||||
水原 雪 (Mizuhara Yuki) - Female
|
||||
彩芽 (Ayame) - Female
|
||||
水原 独苑 (Mizuhara Dokuen) - Male
|
||||
空木 (Utsugi) - Male
|
||||
金目 (Kaname) - Male
|
||||
銀目 (Ginme) - Male
|
||||
ジロウ (Jirou) - Male
|
||||
サクラ (Sakura) - Female
|
||||
ゼフ (Zeff) - Male
|
||||
ヨモダ (Yomada) - Male
|
||||
グダ (Guda) - Male
|
||||
フジワラ (Fujiwara) - Male
|
||||
ナオ (Nao) - Female
|
||||
タジ (Taji) - Male
|
||||
カリン (Karin) - Female
|
||||
セリナ (Serina) - Female
|
||||
ラグ (Ragu) - Male
|
||||
ハッカイ (Hakkai) - Male
|
||||
|
||||
# Lewd Terms
|
||||
マンコ (pussy)
|
||||
|
|
|
|||
Loading…
Reference in a new issue