@umituz/react-native-image 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,260 +0,0 @@
1
- /**
2
- * Infrastructure - Crop Tool
3
- *
4
- * Advanced cropping with aspect ratio and grid guides
5
- */
6
-
7
- export interface CropConfig {
8
- aspectRatio?: number;
9
- lockAspectRatio?: boolean;
10
- showGrid?: boolean;
11
- minSize?: { width: number; height: number };
12
- maxSize?: { width: number; height: number };
13
- }
14
-
15
- export interface CropArea {
16
- x: number;
17
- y: number;
18
- width: number;
19
- height: number;
20
- }
21
-
22
- export interface CropPreset {
23
- name: string;
24
- aspectRatio: number;
25
- icon: string;
26
- }
27
-
28
- export class CropTool {
29
- private static readonly PRESETS: CropPreset[] = [
30
- { name: 'Free', aspectRatio: 0, icon: 'crop-free' },
31
- { name: '1:1', aspectRatio: 1, icon: 'crop-square' },
32
- { name: '4:3', aspectRatio: 4/3, icon: 'crop-landscape' },
33
- { name: '3:4', aspectRatio: 3/4, icon: 'crop-portrait' },
34
- { name: '16:9', aspectRatio: 16/9, icon: 'crop-widescreen' },
35
- { name: '9:16', aspectRatio: 9/16, icon: 'crop-vertical' },
36
- ];
37
-
38
- static getPresets(): CropPreset[] {
39
- return this.PRESETS;
40
- }
41
-
42
- static constrainToAspectRatio(
43
- width: number,
44
- height: number,
45
- aspectRatio: number
46
- ): { width: number; height: number } {
47
- if (aspectRatio === 0) return { width, height };
48
-
49
- const currentRatio = width / height;
50
-
51
- if (currentRatio > aspectRatio) {
52
- // Width is too large, constrain it
53
- return {
54
- width: height * aspectRatio,
55
- height,
56
- };
57
- } else {
58
- // Height is too large, constrain it
59
- return {
60
- width,
61
- height: width / aspectRatio,
62
- };
63
- }
64
- }
65
-
66
- static constrainToBounds(
67
- area: CropArea,
68
- bounds: { width: number; height: number }
69
- ): CropArea {
70
- let { x, y, width, height } = area;
71
-
72
- // Ensure area is within bounds
73
- if (x < 0) {
74
- width += x;
75
- x = 0;
76
- }
77
- if (y < 0) {
78
- height += y;
79
- y = 0;
80
- }
81
-
82
- if (x + width > bounds.width) {
83
- width = bounds.width - x;
84
- }
85
- if (y + height > bounds.height) {
86
- height = bounds.height - y;
87
- }
88
-
89
- return { x, y, width, height };
90
- }
91
-
92
- static applyMinimumSize(
93
- area: CropArea,
94
- minSize: { width: number; height: number }
95
- ): CropArea {
96
- const { width, height } = area;
97
-
98
- return {
99
- ...area,
100
- width: Math.max(width, minSize.width),
101
- height: Math.max(height, minSize.height),
102
- };
103
- }
104
-
105
- static applyMaximumSize(
106
- area: CropArea,
107
- maxSize: { width: number; height: number }
108
- ): CropArea {
109
- const { width, height } = area;
110
-
111
- return {
112
- ...area,
113
- width: Math.min(width, maxSize.width),
114
- height: Math.min(height, maxSize.height),
115
- };
116
- }
117
-
118
- static centerCrop(
119
- imageWidth: number,
120
- imageHeight: number,
121
- targetWidth?: number,
122
- targetHeight?: number
123
- ): CropArea {
124
- if (!targetWidth && !targetHeight) {
125
- return {
126
- x: 0,
127
- y: 0,
128
- width: imageWidth,
129
- height: imageHeight,
130
- };
131
- }
132
-
133
- if (!targetHeight) {
134
- targetHeight = targetWidth! * (imageHeight / imageWidth);
135
- }
136
- if (!targetWidth) {
137
- targetWidth = targetHeight! * (imageWidth / imageHeight);
138
- }
139
-
140
- return {
141
- x: (imageWidth - targetWidth) / 2,
142
- y: (imageHeight - targetHeight) / 2,
143
- width: targetWidth,
144
- height: targetHeight,
145
- };
146
- }
147
-
148
- static drawCropOverlay(
149
- ctx: CanvasRenderingContext2D,
150
- cropArea: CropArea,
151
- config: CropConfig
152
- ): void {
153
- const { x, y, width, height } = cropArea;
154
-
155
- // Draw semi-transparent overlay outside crop area
156
- ctx.save();
157
- ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
158
-
159
- // Top overlay
160
- ctx.fillRect(0, 0, ctx.canvas.width, y);
161
- // Bottom overlay
162
- ctx.fillRect(0, y + height, ctx.canvas.width, ctx.canvas.height - y - height);
163
- // Left overlay
164
- ctx.fillRect(0, y, x, height);
165
- // Right overlay
166
- ctx.fillRect(x + width, y, ctx.canvas.width - x - width, height);
167
-
168
- // Draw crop area border
169
- ctx.strokeStyle = '#ffffff';
170
- ctx.lineWidth = 2;
171
- ctx.setLineDash([5, 5]);
172
- ctx.strokeRect(x, y, width, height);
173
-
174
- // Draw corner handles
175
- ctx.fillStyle = '#ffffff';
176
- const handleSize = 8;
177
- ctx.fillRect(x - handleSize/2, y - handleSize/2, handleSize, handleSize);
178
- ctx.fillRect(x + width - handleSize/2, y - handleSize/2, handleSize, handleSize);
179
- ctx.fillRect(x - handleSize/2, y + height - handleSize/2, handleSize, handleSize);
180
- ctx.fillRect(x + width - handleSize/2, y + height - handleSize/2, handleSize, handleSize);
181
-
182
- ctx.setLineDash([]);
183
- ctx.restore();
184
-
185
- // Draw grid if enabled
186
- if (config.showGrid) {
187
- this.drawGrid(ctx, cropArea);
188
- }
189
- }
190
-
191
- private static drawGrid(
192
- ctx: CanvasRenderingContext2D,
193
- cropArea: CropArea
194
- ): void {
195
- const { x, y, width, height } = cropArea;
196
-
197
- ctx.save();
198
- ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
199
- ctx.lineWidth = 1;
200
- ctx.setLineDash([2, 3]);
201
-
202
- // Third lines
203
- ctx.beginPath();
204
- ctx.moveTo(x + width/3, y);
205
- ctx.lineTo(x + width/3, y + height);
206
- ctx.moveTo(x + 2*width/3, y);
207
- ctx.lineTo(x + 2*width/3, y + height);
208
- ctx.moveTo(x, y + height/3);
209
- ctx.lineTo(x + width, y + height/3);
210
- ctx.moveTo(x, y + 2*height/3);
211
- ctx.lineTo(x + width, y + 2*height/3);
212
- ctx.stroke();
213
-
214
- // Center lines
215
- ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
216
- ctx.setLineDash([5, 2]);
217
- ctx.beginPath();
218
- ctx.moveTo(x + width/2, y);
219
- ctx.lineTo(x + width/2, y + height);
220
- ctx.moveTo(x, y + height/2);
221
- ctx.lineTo(x + width, y + height/2);
222
- ctx.stroke();
223
-
224
- ctx.restore();
225
- }
226
-
227
- static getCropFromSelection(
228
- startPoint: { x: number; y: number },
229
- endPoint: { x: number; y: number },
230
- config: CropConfig
231
- ): CropArea {
232
- const x = Math.min(startPoint.x, endPoint.x);
233
- const y = Math.min(startPoint.y, endPoint.y);
234
- const width = Math.abs(endPoint.x - startPoint.x);
235
- const height = Math.abs(endPoint.y - startPoint.y);
236
-
237
- let cropArea = { x, y, width, height };
238
-
239
- // Apply aspect ratio constraint if locked
240
- if (config.lockAspectRatio && config.aspectRatio) {
241
- const constrained = this.constrainToAspectRatio(width, height, config.aspectRatio);
242
- cropArea = {
243
- x,
244
- y,
245
- width: constrained.width,
246
- height: constrained.height,
247
- };
248
- }
249
-
250
- // Apply size constraints
251
- if (config.minSize) {
252
- cropArea = this.applyMinimumSize(cropArea, config.minSize);
253
- }
254
- if (config.maxSize) {
255
- cropArea = this.applyMaximumSize(cropArea, config.maxSize);
256
- }
257
-
258
- return cropArea;
259
- }
260
- }
@@ -1,210 +0,0 @@
1
- /**
2
- * Infrastructure - Drawing Engine
3
- *
4
- * Core drawing functionality for editor tools
5
- */
6
-
7
- export type DrawingPath = Array<{ x: number; y: number; pressure?: number }>;
8
-
9
- export interface DrawingContext {
10
- canvas: HTMLCanvasElement | any;
11
- ctx: CanvasRenderingContext2D | any;
12
- scale: number;
13
- offset: { x: number; y: number };
14
- }
15
-
16
- export interface DrawingConfig {
17
- color: string;
18
- size: number;
19
- opacity: number;
20
- style: 'normal' | 'marker' | 'spray';
21
- smoothing: boolean;
22
- }
23
-
24
- export class DrawingEngine {
25
- private static smoothPath(path: DrawingPath): DrawingPath {
26
- if (path.length < 3) return path;
27
-
28
- const smoothed: DrawingPath = [path[0]];
29
-
30
- for (let i = 1; i < path.length - 1; i++) {
31
- const prev = path[i - 1];
32
- const curr = path[i];
33
- const next = path[i + 1];
34
-
35
- smoothed.push({
36
- x: curr.x * 0.5 + (prev.x + next.x) * 0.25,
37
- y: curr.y * 0.5 + (prev.y + next.y) * 0.25,
38
- pressure: curr.pressure,
39
- });
40
- }
41
-
42
- smoothed.push(path[path.length - 1]);
43
- return smoothed;
44
- }
45
-
46
- private static drawMarker(
47
- ctx: CanvasRenderingContext2D,
48
- from: { x: number; y: number },
49
- to: { x: number; y: number },
50
- config: DrawingConfig
51
- ): void {
52
- ctx.globalAlpha = config.opacity * 0.3;
53
- const strokeWidth = (config as any).strokeWidth || config.size * 2;
54
- ctx.lineWidth = strokeWidth;
55
-
56
- ctx.beginPath();
57
- ctx.moveTo(from.x, from.y);
58
- ctx.lineTo(to.x, to.y);
59
- ctx.stroke();
60
- }
61
-
62
- private static drawSpray(
63
- ctx: CanvasRenderingContext2D,
64
- point: { x: number; y: number },
65
- config: DrawingConfig
66
- ): void {
67
- const density = config.size * 2;
68
- const radius = config.size;
69
-
70
- for (let i = 0; i < density; i++) {
71
- const angle = Math.random() * Math.PI * 2;
72
- const distance = Math.random() * radius;
73
- const x = point.x + Math.cos(angle) * distance;
74
- const y = point.y + Math.sin(angle) * distance;
75
-
76
- ctx.globalAlpha = config.opacity * Math.random() * 0.5;
77
- ctx.fillRect(x, y, 1, 1);
78
- }
79
- }
80
-
81
- static drawStroke(
82
- ctx: CanvasRenderingContext2D,
83
- path: DrawingPath,
84
- config: DrawingConfig
85
- ): void {
86
- if (path.length < 2) return;
87
-
88
- const smoothedPath = config.smoothing ? this.smoothPath(path) : path;
89
-
90
- ctx.lineCap = 'round';
91
- ctx.lineJoin = 'round';
92
- ctx.strokeStyle = config.color;
93
- ctx.globalAlpha = config.opacity;
94
-
95
- switch (config.style) {
96
- case 'marker':
97
- this.drawMarker(ctx, smoothedPath[0], smoothedPath[smoothedPath.length - 1], config);
98
- break;
99
-
100
- case 'spray':
101
- smoothedPath.forEach(point => this.drawSpray(ctx, point, config));
102
- break;
103
-
104
- default:
105
- ctx.lineWidth = config.size;
106
- ctx.beginPath();
107
- ctx.moveTo(smoothedPath[0].x, smoothedPath[0].y);
108
-
109
- for (let i = 1; i < smoothedPath.length; i++) {
110
- ctx.lineTo(smoothedPath[i].x, smoothedPath[i].y);
111
- }
112
- ctx.stroke();
113
- }
114
- }
115
-
116
- static drawShape(
117
- ctx: CanvasRenderingContext2D,
118
- type: 'rectangle' | 'circle' | 'line' | 'arrow',
119
- start: { x: number; y: number },
120
- end: { x: number; y: number },
121
- config: Partial<DrawingConfig>
122
- ): void {
123
- const cfg = config as any;
124
- const color = cfg.color || '#000000';
125
- const size = cfg.size || 2;
126
- const opacity = cfg.opacity || 1;
127
- const strokeWidth = cfg.strokeWidth || 2;
128
-
129
- ctx.strokeStyle = color;
130
- ctx.fillStyle = color;
131
- ctx.lineWidth = strokeWidth;
132
- ctx.globalAlpha = opacity;
133
- ctx.lineCap = 'round';
134
-
135
- switch (type) {
136
- case 'rectangle':
137
- const width = end.x - start.x;
138
- const height = end.y - start.y;
139
- ctx.strokeRect(start.x, start.y, width, height);
140
- break;
141
-
142
- case 'circle':
143
- const radius = Math.sqrt(
144
- Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)
145
- );
146
- ctx.beginPath();
147
- ctx.arc(start.x, start.y, radius, 0, 2 * Math.PI);
148
- ctx.stroke();
149
- break;
150
-
151
- case 'line':
152
- ctx.beginPath();
153
- ctx.moveTo(start.x, start.y);
154
- ctx.lineTo(end.x, end.y);
155
- ctx.stroke();
156
- break;
157
-
158
- case 'arrow':
159
- const angle = Math.atan2(end.y - start.y, end.x - start.x);
160
- const arrowLength = 15;
161
- const arrowAngle = Math.PI / 6;
162
-
163
- // Draw line
164
- ctx.beginPath();
165
- ctx.moveTo(start.x, start.y);
166
- ctx.lineTo(end.x, end.y);
167
- ctx.stroke();
168
-
169
- // Draw arrowhead
170
- ctx.beginPath();
171
- ctx.moveTo(end.x, end.y);
172
- ctx.lineTo(
173
- end.x - arrowLength * Math.cos(angle - arrowAngle),
174
- end.y - arrowLength * Math.sin(angle - arrowAngle)
175
- );
176
- ctx.moveTo(end.x, end.y);
177
- ctx.lineTo(
178
- end.x - arrowLength * Math.cos(angle + arrowAngle),
179
- end.y - arrowLength * Math.sin(angle + arrowAngle)
180
- );
181
- ctx.stroke();
182
- break;
183
- }
184
- }
185
-
186
- static erase(
187
- ctx: CanvasRenderingContext2D,
188
- position: { x: number; y: number },
189
- size: number
190
- ): void {
191
- ctx.globalCompositeOperation = 'destination-out';
192
- ctx.beginPath();
193
- ctx.arc(position.x, position.y, size, 0, 2 * Math.PI);
194
- ctx.fill();
195
- ctx.globalCompositeOperation = 'source-over';
196
- }
197
-
198
- static createDrawingContext(
199
- canvas: HTMLCanvasElement | any,
200
- scale: number = 1,
201
- offset: { x: number; y: number } = { x: 0, y: 0 }
202
- ): DrawingContext {
203
- return {
204
- canvas,
205
- ctx: canvas.getContext('2d'),
206
- scale,
207
- offset,
208
- };
209
- }
210
- }
@@ -1,51 +0,0 @@
1
- /**
2
- * Image Infrastructure - Filter Effects
3
- *
4
- * Advanced filter effects and color processing
5
- */
6
-
7
- export class FilterEffects {
8
- static applyVintage(imageData: ImageData): ImageData {
9
- let data = FilterEffects.applySepia(imageData, 0.8);
10
- const { width, height } = imageData;
11
- const centerX = width / 2;
12
- const centerY = height / 2;
13
- const maxDistance = Math.sqrt(centerX * centerX + centerY * centerY);
14
-
15
- for (let y = 0; y < height; y++) {
16
- for (let x = 0; x < width; x++) {
17
- const distance = Math.sqrt((x - centerX) ** 2 + (y - centerY) ** 2);
18
- const vignette = 1 - (distance / maxDistance) * 0.7;
19
- const i = (y * width + x) * 4;
20
-
21
- data.data[i] *= vignette;
22
- data.data[i + 1] *= vignette;
23
- data.data[i + 2] *= vignette;
24
- }
25
- }
26
-
27
- return data;
28
- }
29
-
30
- static applySepia(imageData: ImageData, intensity: number = 1): ImageData {
31
- const data = new Uint8ClampedArray(imageData.data);
32
- for (let i = 0; i < data.length; i += 4) {
33
- const r = data[i];
34
- const g = data[i + 1];
35
- const b = data[i + 2];
36
-
37
- data[i] = Math.min(255, (r * (1 - (0.607 * intensity))) + (g * (0.769 * intensity)) + (b * (0.189 * intensity)));
38
- data[i + 1] = Math.min(255, (r * (0.349 * intensity)) + (g * (1 - (0.314 * intensity))) + (b * (0.168 * intensity)));
39
- data[i + 2] = Math.min(255, (r * (0.272 * intensity)) + (g * (0.534 * intensity)) + (b * (1 - (0.869 * intensity))));
40
- }
41
- return FilterEffects.createCanvasImageData(imageData.width, imageData.height, data);
42
- }
43
-
44
- static createCanvasImageData(
45
- width: number,
46
- height: number,
47
- data: Uint8ClampedArray
48
- ): ImageData {
49
- return { data, width, height } as ImageData;
50
- }
51
- }
@@ -1,168 +0,0 @@
1
- /**
2
- * Infrastructure - Shape Renderer
3
- *
4
- * Advanced shape drawing with different styles
5
- */
6
-
7
- export interface ShapeStyle {
8
- fill?: string;
9
- stroke?: string;
10
- strokeWidth?: number;
11
- dash?: number[];
12
- opacity?: number;
13
- }
14
-
15
- export class ShapeRenderer {
16
- static drawRoundedRect(
17
- ctx: CanvasRenderingContext2D,
18
- x: number,
19
- y: number,
20
- width: number,
21
- height: number,
22
- radius: number,
23
- style: ShapeStyle
24
- ): void {
25
- ctx.save();
26
-
27
- ctx.globalAlpha = style.opacity || 1;
28
- ctx.strokeStyle = style.stroke || '#000000';
29
- ctx.fillStyle = style.fill || 'transparent';
30
- ctx.lineWidth = style.strokeWidth || 2;
31
-
32
- if (style.dash) {
33
- ctx.setLineDash(style.dash);
34
- }
35
-
36
- ctx.beginPath();
37
- ctx.moveTo(x + radius, y);
38
- ctx.lineTo(x + width - radius, y);
39
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
40
- ctx.lineTo(x + width, y + height - radius);
41
- ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
42
- ctx.lineTo(x + radius, y + height);
43
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
44
- ctx.lineTo(x, y + radius);
45
- ctx.quadraticCurveTo(x, y, x + radius, y);
46
- ctx.closePath();
47
-
48
- if (style.fill) ctx.fill();
49
- if (style.stroke) ctx.stroke();
50
-
51
- ctx.restore();
52
- }
53
-
54
- static drawStar(
55
- ctx: CanvasRenderingContext2D,
56
- cx: number,
57
- cy: number,
58
- outerRadius: number,
59
- innerRadius: number,
60
- points: number,
61
- style: ShapeStyle
62
- ): void {
63
- ctx.save();
64
-
65
- ctx.globalAlpha = style.opacity || 1;
66
- ctx.strokeStyle = style.stroke || '#000000';
67
- ctx.fillStyle = style.fill || 'transparent';
68
- ctx.lineWidth = style.strokeWidth || 2;
69
-
70
- ctx.beginPath();
71
- for (let i = 0; i < points * 2; i++) {
72
- const angle = (Math.PI * i) / points - Math.PI / 2;
73
- const radius = i % 2 === 0 ? outerRadius : innerRadius;
74
- const x = cx + Math.cos(angle) * radius;
75
- const y = cy + Math.sin(angle) * radius;
76
-
77
- if (i === 0) {
78
- ctx.moveTo(x, y);
79
- } else {
80
- ctx.lineTo(x, y);
81
- }
82
- }
83
- ctx.closePath();
84
-
85
- if (style.fill) ctx.fill();
86
- if (style.stroke) ctx.stroke();
87
-
88
- ctx.restore();
89
- }
90
-
91
- static drawHeart(
92
- ctx: CanvasRenderingContext2D,
93
- x: number,
94
- y: number,
95
- size: number,
96
- style: ShapeStyle
97
- ): void {
98
- ctx.save();
99
-
100
- ctx.globalAlpha = style.opacity || 1;
101
- ctx.strokeStyle = style.stroke || '#000000';
102
- ctx.fillStyle = style.fill || 'transparent';
103
- ctx.lineWidth = style.strokeWidth || 2;
104
-
105
- ctx.beginPath();
106
- const topCurveHeight = size * 0.3;
107
- ctx.moveTo(x, y + topCurveHeight);
108
-
109
- // Top left curve
110
- ctx.bezierCurveTo(
111
- x, y,
112
- x - size / 2, y,
113
- x - size / 2, y + topCurveHeight
114
- );
115
-
116
- // Bottom left curve
117
- ctx.bezierCurveTo(
118
- x - size / 2, y + (size + topCurveHeight) / 2,
119
- x, y + (size + topCurveHeight) / 1.5,
120
- x, y + size
121
- );
122
-
123
- // Bottom right curve
124
- ctx.bezierCurveTo(
125
- x, y + (size + topCurveHeight) / 1.5,
126
- x + size / 2, y + (size + topCurveHeight) / 2,
127
- x + size / 2, y + topCurveHeight
128
- );
129
-
130
- // Top right curve
131
- ctx.bezierCurveTo(
132
- x + size / 2, y,
133
- x, y,
134
- x, y + topCurveHeight
135
- );
136
-
137
- ctx.closePath();
138
-
139
- if (style.fill) ctx.fill();
140
- if (style.stroke) ctx.stroke();
141
-
142
- ctx.restore();
143
- }
144
-
145
- static drawTriangle(
146
- ctx: CanvasRenderingContext2D,
147
- points: Array<{ x: number; y: number }>,
148
- style: ShapeStyle
149
- ): void {
150
- ctx.save();
151
-
152
- ctx.globalAlpha = style.opacity || 1;
153
- ctx.strokeStyle = style.stroke || '#000000';
154
- ctx.fillStyle = style.fill || 'transparent';
155
- ctx.lineWidth = style.strokeWidth || 2;
156
-
157
- ctx.beginPath();
158
- ctx.moveTo(points[0].x, points[0].y);
159
- ctx.lineTo(points[1].x, points[1].y);
160
- ctx.lineTo(points[2].x, points[2].y);
161
- ctx.closePath();
162
-
163
- if (style.fill) ctx.fill();
164
- if (style.stroke) ctx.stroke();
165
-
166
- ctx.restore();
167
- }
168
- }