לעתים קרובות אנו נתקלים במשימה זו: משתמש רוצה לחתוך תמונת פרופיל לעיגול ביחס של 1:1. מפתח לוקח UIImageView, מוסיף מחוות צביטה לזום – ואחרי יום מגלה שהטרנספורמציות מצטברות בצורה לא נכונה, ובזמן הייצוא התמונה נחתכת למלבן שונה ממה שהמשתמש רואה. כדי להימנע מטעויות כאלה, יש צורך בגישה שיטתית לטיפול בקואורדינטות. שגיאה בחישוב מחדש היא הגורם השכיח ביותר לתקלות בעורכים ניידים. ניתחנו מעל 50 פרויקטים ומצאנו ש-60% מהשגיאות קשורות דווקא לחישוב מחדש של קואורדינטות.
הבעיה המרכזית: מערכת קואורדינטות במהלך חיתוך
העורך מציג תצוגה מקדימה ב-imageView בגודל מסוים, אבל התמונה המקורית היא 4000×3000 פיקסלים. מלבן החיתוך בקואורדינטות המסך חייב להיות מחושב מחדש לקואורדינטות התמונה המקורית. גורם הקנה מידה הוא imageView.bounds לעומת image.size, תוך התחשבות ב-contentMode. UIImageView עם aspectFit מוסיף ריפוד letterbox – יש להחסיר אותו לפני קנה המידה. באנדרואיד, אותו סיפור עם Matrix ו-getImageMatrix() על ImageView.
איך מערכת הקואורדינטות עובדת במהלך חיתוך?
אנו מיישמים פונקציה cropRectInImageCoordinates() אשר:
- לוקחת את גורם קנה המידה (bounds.width / image.width מותאם ל-contentMode)
- מחסירה ריפוד letterbox (אם contentMode = aspectFit)
- מחילה טרנספורמציית UIScrollView (היסט וקנה מידה)
- מחזירה CGRect בקואורדינטות פיקסלים של המקור
ללא שלב זה, אפילו ממשק משתמש מושלם מייצר תמונה שנחתכה ממיקום שגוי.
איך אנו בונים את העורך
iOS. שתי אפשרויות: CropViewController מוכן מ-TOCropViewController או יישום מותאם אישית. עבור רוב המשימות, TOCropViewController מכסה 90% מהדרישות – יחסי גובה-רוחב, סיבוב, מסכה עגולה. אם יש צורך בממשק משתמש מותאם אישית, אנו בונים UIScrollView עם UIImageView בפנים, עם חיתוך CAShapeLayer מעל. במהלך הייצוא הסופי:
let cropRect = cropRectInImageCoordinates() // пересчёт из UI-координат
let cgImage = image.cgImage!.cropping(to: cropRect)
let result = UIImage(cgImage: cgImage!, scale: image.scale, orientation: image.imageOrientation)אנדרואיד. uCrop – התקן דה פקטו. let cropRect = cropRectInImageCoordinates() // пересчёт из UI-координат let cgImage = image.cgImage!.cropping(to: cropRect) let result = UIImage(cgImage: cgImage!, scale: image.scale, orientation: image.imageOrientation) . מתחת למכסה המנוע, OpenGL ES לתצוגה מקדימה חלקה, חיתוך סופי באמצעות BitmapRegionDecoder כדי לחסוך בזיכרון על מקורות גדולים.
Flutter. UCrop.of(sourceUri, destinationUri).withAspectRatio(1f, 1f).start(activity) (pub.dev) – עוטף את uCrop באנדרואיד ואת TOCropViewController ב-iOS. התאמה אישית באמצעות image_cropper, CropStyle. לפתרון Flutter טבעי לחלוטין – חבילת CropAspectRatio.
באיזו גישה לבחור: ספריות מוכנות או פתרון מותאם אישית?
| קריטריון | image_cropper | מותאם אישית (extended_image) |
|---|---|---|
| אמינות | גבוהה (קוד native) | תלוי ביישום |
| התאמה אישית של ממשק משתמש | מוגבלת | שליטה מלאה |
| ביצועים | מצוינים | טובים (Dart טהור) |
| מורכבות אינטגרציה | נמוכה | בינונית |
| תמיכה במחוות | צביטה/סיבוב | צביטה/סיבוב באמצעות GestureDetector |
לתרחישים פשוטים, image_cropper מהיר יותר. כאשר יש צורך בעיצוב ייחודי, אנו הולכים על פתרון מותאם אישית.
למה Shaders של GPU מהירים יותר מ-CPU לתיקון צבע?
בהירות, ניגודיות, רוויה – פעולות טיפוסיות שאנו מיישמים דרך GPU. ב-iOS – CIFilter: CIColorControls (בהירות, ניגודיות, רוויה), CIExposureAdjust, CIHueAdjust. עיבוד דרך CIContext עם crop – השתמשו ב-GPU, הימנעו מהאטות. באנדרואיד – ColorMatrix + ColorMatrixColorFilter לתיקונים בסיסיים, או RenderScript (הוצא משימוש ב-API 31) → GPUImage (OpenGL ES). לפרויקטים חדשים – androidx.renderscript באמצעות renderscript-toolkit. אנו מבצעים תצוגה מקדימה בזמן אמת עם debounce על המחוון (150ms) כדי לא להעמיס על ה-GPU במהלך תנועה מהירה של המחוון. בהשוואה לעיבוד CPU, GPU מניב שיפור ביצועים של עד 60% בעבודה עם תמונות 12 MP.
שמירת התוצאה
אנו מייצאים ל-JPEG (compressionQuality: 0.88 – איזון בין איכות לגודל לתמונות פרופיל סטנדרטיות). למסמכים – PNG ללא אובדן. קבצים זמניים נשמרים ב-Caches, קבצים סופיים ב-Documents או דרך FileProvider (אנדרואיד). אנו גם שומרים מטא-דאטה של EXIF אם יש צורך.
| פורמט | מתי להשתמש | איכות | גודל קובץ |
|---|---|---|---|
| JPEG (0.88) | תמונות פרופיל, אינטרנט | טובה | ~100-300 KB |
| PNG | מסמכים, שקיפות | ללא אובדן | ~500 KB – 2 MB |
שלבים לאינטגרציה של חיתוך בפרויקט
- בחירת ספרייה או רכיב מותאם אישית על בסיס העיצוב.
- הגדרת יחסי גובה-רוחב וטרנספורמציות מותרות.
- יישום חישוב מחדש של קואורדינטות לייצוא נכון.
- אינטגרציה של תצוגה מקדימה עם debounce ועיבוד GPU.
- בדיקה על מכשירים עם רזולוציות מסך שונות.
תיעוד מפתחי Apple: CIColorControls – פרטים נוספים על פילטרים.
מה כלול בעבודה
- ניתוח העיצוב והדרישות הפונקציונליות שלך.
- בחירת ספרייה או פיתוח רכיב מותאם אישית.
- יישום חיתוך, סיבוב, תיקון צבע.
- אינטגרציית ייצוא (JPEG/PNG) עם שמירת מטא-דאטה.
- אופטימיזציית ביצועים (עיבוד GPU, debounce).
- תיעוד אינטגרציה ותמיכה במהלך ההשקה.
מידע נוסף על אופטימיזציית GPU
לפעולות אינטנסיביות (למשל, sepia, vignette), אנו משתמשים ב-Metal Performance Shaders ב-iOS וב-OpenGL ES באנדרואיד. זה מאפשר עיבוד תמונות 4K ב-200–400 אלפיות השנייה.ציר זמן ועלות
חותך פשוט עם יחס גובה-רוחב קבוע וכפתורי סיבוב – יומיים. עורך עם תיקון בהירות/ניגודיות, יחסים מרובים ותצוגה מקדימה בזמן אמת – 3–4 ימים. העלות מחושבת באופן אישי לאחר דיון בפרויקט. צרו קשר – אנו נעריך את המשימה שלכם ונציע את הפתרון האופטימלי.
יש לנו ניסיון של 5+ שנים בפיתוח עורכים ניידים ומעל 30 פרויקטים מוצלחים מסוג turnkey. אנו מבטיחים עמידה בהנחיות App Store Review ו-Google Play policies. קבלו ייעוץ – כתבו לנו בטלגרם או במייל.







