返回提交历史
Modified
g4f/Provider/needs_auth/PuterJS.py
+1
-0
Modified
g4f/api/__init__.py
+17
-17
Modified
g4f/gui/server/backend_api.py
+1
-2
Modified
g4f/image/__init__.py
+26
-5
XFEstudio/gpt4free
Update process generate thumbnails
c6bfddec
代码差异
4 个文件
+45
-24
@@ -20,6 +20,7 @@ class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
20
20
login_url = "https://github.com/HeyPuter/puter-cli"
21
21
api_endpoint = "https://api.puter.com/drivers/call"
22
22
working = True
23
active_by_default = True
23
24
needs_auth = True
24
25
25
26
default_model = 'gpt-4o'
@@ -681,25 +681,13 @@ class Api:
681
681
other_name = os.path.join(get_media_dir(), os.path.basename(quote_plus(filename)))
682
682
if os.path.isfile(other_name):
683
683
target = other_name
684
if thumbnail and has_pillow:
685
thumbnail_dir = os.path.join(get_media_dir(), "thumbnails")
686
thumbnail = os.path.join(thumbnail_dir, filename)
687
try:
688
if not os.path.isfile(thumbnail):
689
image = Image.open(target)
690
os.makedirs(thumbnail_dir, exist_ok=True)
691
image = process_image(image)
692
image.save(os.path.join(thumbnail_dir, filename))
693
except Exception as e:
694
logger.exception(e)
695
if os.path.isfile(thumbnail):
696
target = thumbnail
684
result = target
697
685
ext = os.path.splitext(filename)[1][1:]
698
686
mime_type = EXTENSIONS_MAP.get(ext)
699
687
stat_result = SimpleNamespace()
700
688
stat_result.st_size = 0
701
if os.path.isfile(target):
702
stat_result.st_size = os.stat(target).st_size
689
if os.path.isfile(result):
690
stat_result.st_size = os.stat(result).st_size
703
691
stat_result.st_mtime = int(f"{filename.split('_')[0]}") if filename.startswith("1") else 0
704
692
headers = {
705
693
"cache-control": "public, max-age=31536000",
@@ -742,10 +730,22 @@ class Api:
742
730
debug.error(f"Download failed: {source_url}")
743
731
debug.error(e)
744
732
return RedirectResponse(url=source_url)
745
if not os.path.isfile(target):
733
if thumbnail and has_pillow:
734
thumbnail_dir = os.path.join(get_media_dir(), "thumbnails")
735
thumbnail = os.path.join(thumbnail_dir, filename)
736
try:
737
if not os.path.isfile(thumbnail):
738
image = Image.open(target)
739
os.makedirs(thumbnail_dir, exist_ok=True)
740
process_image(image, save=os.path.join(thumbnail_dir, filename))
741
except Exception as e:
742
logger.exception(e)
743
if os.path.isfile(thumbnail):
744
result = thumbnail
745
if not os.path.isfile(result):
746
746
return ErrorResponse.from_message("File not found", HTTP_404_NOT_FOUND)
747
747
async def stream():
748
with open(target, "rb") as file:
748
with open(result, "rb") as file:
749
749
while True:
750
750
chunk = file.read(65536)
751
751
if not chunk:
@@ -383,8 +383,7 @@ class Backend_Api(Api):
383
383
image = Image.open(copyfile)
384
384
thumbnail_dir = os.path.join(bucket_dir, "thumbnail")
385
385
os.makedirs(thumbnail_dir, exist_ok=True)
386
image = process_image(image)
387
image.save(os.path.join(thumbnail_dir, filename))
386
process_image(image, save=os.path.join(thumbnail_dir, filename))
388
387
except Exception as e:
389
388
logger.exception(e)
390
389
elif is_supported:
@@ -7,6 +7,8 @@ import base64
7
7
from io import BytesIO
8
8
from pathlib import Path
9
9
from typing import Optional
10
from collections import defaultdict
11
10
12
try:
11
13
from PIL.Image import open as open_image, new as new_image
12
14
from PIL.Image import FLIP_LEFT_RIGHT, ROTATE_180, ROTATE_270, ROTATE_90
@@ -14,9 +16,15 @@ try:
14
16
has_requirements = True
15
17
except ImportError:
16
18
has_requirements = False
19
try:
20
import piexif
21
has_piexif = True
22
except ImportError:
23
has_piexif = False
17
24
18
25
from ..typing import ImageType, Image
19
26
from ..errors import MissingRequirementsError
27
from .. import debug
20
28
21
29
EXTENSIONS_MAP: dict[str, str] = {
22
30
# Image
@@ -201,6 +209,11 @@ def extract_data_uri(data_uri: str) -> bytes:
201
209
data = base64.b64decode(data)
202
210
return data
203
211
212
def get_orientation_key() -> int:
213
for tag, value in ExifTags.TAGS.items():
214
if value == 'Orientation':
215
return tag
216
204
217
def get_orientation(image: Image) -> int:
205
218
"""
206
219
Gets the orientation of the given image.
@@ -212,12 +225,9 @@ def get_orientation(image: Image) -> int:
212
225
int: The orientation value.
213
226
"""
214
227
exif_data = image.getexif() if hasattr(image, 'getexif') else image._getexif()
215
if exif_data:
216
for tag, value in ExifTags.TAGS.items():
217
if value == 'Orientation':
218
return exif_data.get(tag)
228
return exif_data.get(get_orientation_key()) if exif_data else None
219
229
220
def process_image(image: Image, new_width: int = 800, new_height: int = 800) -> Image:
230
def process_image(image: Image, new_width: int = 800, new_height: int = 800, save: str = None) -> Image:
221
231
"""
222
232
Processes the given image by adjusting its orientation and resizing it.
223
233
@@ -232,6 +242,7 @@ def process_image(image: Image, new_width: int = 800, new_height: int = 800) ->
232
242
# Fix orientation
233
243
orientation = get_orientation(image)
234
244
if orientation:
245
debug.log(f"Image orientation: {orientation}")
235
246
if orientation > 4:
236
247
image = image.transpose(FLIP_LEFT_RIGHT)
237
248
if orientation in [3, 4]:
@@ -251,6 +262,16 @@ def process_image(image: Image, new_width: int = 800, new_height: int = 800) ->
251
262
# Convert to RGB for jpg format
252
263
elif image.mode != "RGB":
253
264
image = image.convert("RGB")
265
# Remove EXIF data
266
if has_piexif and save is not None:
267
try:
268
exif_dict = piexif.load(image.info["exif"])
269
except KeyError:
270
exif_dict = defaultdict(dict)
271
if exif_dict['Exif']:
272
exif_dict['Exif'] = {}
273
elif save is not None:
274
image.save(save)
254
275
return image
255
276
256
277
def to_bytes(image: ImageType) -> bytes: