diff --git a/servers/fastapi/models/pptx_models.py b/servers/fastapi/models/pptx_models.py index 48ff2308..ad596481 100644 --- a/servers/fastapi/models/pptx_models.py +++ b/servers/fastapi/models/pptx_models.py @@ -133,7 +133,7 @@ class PptxPictureBoxModel(PptxShapeModel): margin: Optional[PptxSpacingModel] = None clip: bool = True opacity: Optional[float] = None - overlay: Optional[str] = None + invert: bool = False border_radius: Optional[List[int]] = None shape: Optional[PptxBoxShapeEnum] = None object_fit: Optional[PptxObjectFitModel] = None diff --git a/servers/fastapi/services/pptx_presentation_creator.py b/servers/fastapi/services/pptx_presentation_creator.py index 4db980ec..cf387b6c 100644 --- a/servers/fastapi/services/pptx_presentation_creator.py +++ b/servers/fastapi/services/pptx_presentation_creator.py @@ -34,10 +34,10 @@ from models.pptx_models import ( ) from utils.download_helpers import download_files from utils.image_utils import ( - change_image_color, clip_image, create_circle_image, fit_image, + invert_image, round_image_corners, set_image_opacity, ) @@ -174,7 +174,7 @@ class PptxPresentationCreator: if ( picture_model.clip or picture_model.border_radius - or picture_model.overlay + or picture_model.invert or picture_model.opacity or picture_model.object_fit or picture_model.shape @@ -206,8 +206,8 @@ class PptxPresentationCreator: image = round_image_corners(image, picture_model.border_radius) if picture_model.shape == PptxBoxShapeEnum.CIRCLE: image = create_circle_image(image) - if picture_model.overlay: - image = change_image_color(image, picture_model.overlay) + if picture_model.invert: + image = invert_image(image) if picture_model.opacity: image = set_image_opacity(image, picture_model.opacity) image_path = os.path.join(self._temp_dir, f"{str(uuid.uuid4())}.png") diff --git a/servers/fastapi/utils/image_utils.py b/servers/fastapi/utils/image_utils.py index 29cd3a50..3e8ebae8 100644 --- a/servers/fastapi/utils/image_utils.py +++ b/servers/fastapi/utils/image_utils.py @@ -116,17 +116,7 @@ def round_image_corners(image: Image.Image, radii: List[int]) -> Image.Image: return result -def change_image_color(img: Image.Image, color: str) -> Image.Image: - # r, g, b, alpha = img.split() - - # color_overlay = Image.new("RGBA", img.size, color=f"#{color}") - # return Image.composite(color_overlay, img, alpha) - if color.startswith("#"): - color = color[1:] - r_new = int(color[:2], 16) - g_new = int(color[2:4], 16) - b_new = int(color[4:], 16) - +def invert_image(img: Image.Image) -> Image.Image: # Get image data data = img.getdata() @@ -136,9 +126,9 @@ def change_image_color(img: Image.Image, color: str) -> Image.Image: # Get current pixel values r, g, b, a = item - # Apply new color while preserving transparency + # Invert RGB values while preserving transparency if a != 0: # Skip fully transparent pixels - new_data.append((r_new, g_new, b_new, a)) + new_data.append((255 - r, 255 - g, 255 - b, a)) else: new_data.append((0, 0, 0, 0)) diff --git a/servers/nextjs/presentation-layouts/ExampleSlideLayout.tsx b/servers/nextjs/presentation-layouts/ExampleSlideLayout.tsx index 60ab9776..583d6524 100644 --- a/servers/nextjs/presentation-layouts/ExampleSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/ExampleSlideLayout.tsx @@ -38,7 +38,7 @@ export const Schema = z.object({ }), trendIcon: IconSchema.default({ - __icon_url__: "https://example.com/trend-up.svg", + __icon_url__: "/static/icons/placeholder.png", __icon_query__: "upward trend arrow icon" }).meta({ description: "Trend indicator icon", diff --git a/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx index a0b68ade..5acad87d 100644 --- a/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx @@ -37,7 +37,7 @@ const type10SlideSchema = z.object({ })).min(2).max(3).default(() => [ { icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'A beautiful road in the mountains' }, heading: 'First Key Point', @@ -45,7 +45,7 @@ const type10SlideSchema = z.object({ }, { icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'A beautiful road in the mountains' }, heading: 'Second Key Point', diff --git a/servers/nextjs/presentation-layouts/classic/Type6SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type6SlideLayout.tsx index f7d6fff6..004dadd3 100644 --- a/servers/nextjs/presentation-layouts/classic/Type6SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type6SlideLayout.tsx @@ -23,7 +23,7 @@ const type6SlideSchema = z.object({ heading: 'Professional Service', description: 'High-quality professional services tailored to your specific needs and requirements', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Professional Service' } }, @@ -31,7 +31,7 @@ const type6SlideSchema = z.object({ heading: 'Expert Consultation', description: 'Expert advice and consultation from experienced professionals in the field', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Expert Consultation' } }, @@ -39,7 +39,7 @@ const type6SlideSchema = z.object({ heading: 'Quality Assurance', description: 'Comprehensive quality assurance processes to ensure excellent results', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Quality Assurance' } }, @@ -47,7 +47,7 @@ const type6SlideSchema = z.object({ heading: 'Customer Support', description: 'Dedicated customer support available to assist you throughout the process', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Customer Support' } } diff --git a/servers/nextjs/presentation-layouts/classic/Type7SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type7SlideLayout.tsx index 7c40b72e..818e12d1 100644 --- a/servers/nextjs/presentation-layouts/classic/Type7SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type7SlideLayout.tsx @@ -18,7 +18,7 @@ const type7SlideSchema = z.object({ description: "Item description", }), icon: IconSchema.default({ - __icon_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Default icon' }).meta({ description: "Icon for the item", @@ -28,7 +28,7 @@ const type7SlideSchema = z.object({ heading: 'Professional Service', description: 'High-quality professional services tailored to your specific needs and requirements', icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Professional service icon' } }, @@ -36,7 +36,7 @@ const type7SlideSchema = z.object({ heading: 'Expert Consultation', description: 'Expert advice and consultation from experienced professionals in the field', icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2016/02/19/11/19/office-1209640_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Expert consultation icon' } }, @@ -44,7 +44,7 @@ const type7SlideSchema = z.object({ heading: 'Quality Assurance', description: 'Comprehensive quality assurance processes to ensure excellent results', icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2017/08/10/08/47/laptop-2619235_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Quality assurance icon' } }, @@ -52,7 +52,7 @@ const type7SlideSchema = z.object({ heading: 'Customer Support', description: 'Dedicated customer support available to assist you throughout the process', icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Customer support icon' } } diff --git a/servers/nextjs/presentation-layouts/classic/Type8SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type8SlideLayout.tsx index 94e2a502..37002b4b 100644 --- a/servers/nextjs/presentation-layouts/classic/Type8SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type8SlideLayout.tsx @@ -21,7 +21,7 @@ const type8SlideSchema = z.object({ description: "Item description", }), icon: IconSchema.default({ - __icon_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Default icon' }).meta({ description: "Icon for the item", @@ -31,7 +31,7 @@ const type8SlideSchema = z.object({ heading: 'Advanced Features', description: 'Cutting-edge functionality designed to enhance productivity and user experience', icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Advanced features icon' } }, @@ -39,7 +39,7 @@ const type8SlideSchema = z.object({ heading: 'Reliable Performance', description: 'Consistent and dependable performance across all platforms and devices', icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2016/02/19/11/19/office-1209640_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Reliable performance icon' } }, @@ -47,7 +47,7 @@ const type8SlideSchema = z.object({ heading: 'Secure Environment', description: 'Enterprise-grade security measures to protect your data and privacy', icon: { - __icon_url__: 'https://cdn.pixabay.com/photo/2017/08/10/08/47/laptop-2619235_1280.jpg', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'Secure environment icon' } } diff --git a/servers/nextjs/presentation-layouts/general/BulletWithIconsSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/BulletWithIconsSlideLayout.tsx index 088db670..c020d4c2 100644 --- a/servers/nextjs/presentation-layouts/general/BulletWithIconsSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/BulletWithIconsSlideLayout.tsx @@ -32,7 +32,7 @@ const bulletWithIconsSlideSchema = z.object({ title: 'Inefficiency', description: 'Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/alert-triangle.js', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'warning alert inefficiency' } }, @@ -40,7 +40,7 @@ const bulletWithIconsSlideSchema = z.object({ title: 'High Costs', description: 'Outdated systems increase expenses, while small businesses struggle to expand their market reach.', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/trending-up.js', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'trending up costs chart' } } diff --git a/servers/nextjs/presentation-layouts/general/ChartWithBulletsSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/ChartWithBulletsSlideLayout.tsx index 4e1f49aa..a7154e8f 100644 --- a/servers/nextjs/presentation-layouts/general/ChartWithBulletsSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/ChartWithBulletsSlideLayout.tsx @@ -64,7 +64,7 @@ const chartWithBulletsSlideSchema = z.object({ title: 'Total Addressable Market', description: 'Companies can use TAM to plan future expansion and investment.', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/target.js', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'target market scope' } }, @@ -72,7 +72,7 @@ const chartWithBulletsSlideSchema = z.object({ title: 'Serviceable Available Market', description: 'Indicates more measurable market segments for sales efforts.', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/pie-chart.js', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'pie chart analysis' } }, @@ -80,7 +80,7 @@ const chartWithBulletsSlideSchema = z.object({ title: 'Serviceable Obtainable Market', description: 'Help companies plan development strategies according to the market.', icon: { - __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/trending-up.js', + __icon_url__: '/static/icons/placeholder.png', __icon_query__: 'trending up growth' } } diff --git a/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx index 3601aad9..0471c3c6 100644 --- a/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx @@ -44,7 +44,7 @@ const problemStatementSlideSchema = z.object({ "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", icon: { __icon_url__: - "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/alert-triangle.js", + "/static/icons/placeholder.png", __icon_query__: "warning alert inefficiency", }, }, @@ -54,7 +54,7 @@ const problemStatementSlideSchema = z.object({ "Outdated systems increase expenses, while small businesses struggle to expand their market reach.", icon: { __icon_url__: - "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/trending-up.js", + "/static/icons/placeholder.png", __icon_query__: "trending up costs chart", }, }, @@ -64,7 +64,7 @@ const problemStatementSlideSchema = z.object({ "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", icon: { __icon_url__: - "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/alert-triangle.js", + "/static/icons/placeholder.png", __icon_query__: "warning alert inefficiency", }, }, @@ -74,7 +74,7 @@ const problemStatementSlideSchema = z.object({ "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", icon: { __icon_url__: - "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/alert-triangle.js", + "/static/icons/placeholder.png", __icon_query__: "warning alert inefficiency", }, }, diff --git a/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx index 1d6659c7..d428e35e 100644 --- a/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx @@ -51,7 +51,7 @@ const solutionSlideSchema = z.object({ icon: { __icon_query__: "market innovation", __icon_url__: - "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/globe.js", + "/static/icons/placeholder.png", }, }, { @@ -60,7 +60,7 @@ const solutionSlideSchema = z.object({ icon: { __icon_query__: "industry building", __icon_url__: - "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/building.js", + "/static/icons/placeholder.png", }, }, { @@ -69,7 +69,7 @@ const solutionSlideSchema = z.object({ icon: { __icon_query__: "SEM data analysis", __icon_url__: - "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/chart-bar.js", + "/static/icons/placeholder.png", }, }, { @@ -78,7 +78,7 @@ const solutionSlideSchema = z.object({ icon: { __icon_query__: "end user impact", __icon_url__: - "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/user.js", + "/static/icons/placeholder.png", }, }, ]) diff --git a/servers/nextjs/types/pptx_models.ts b/servers/nextjs/types/pptx_models.ts index c7efd5bb..7ece780d 100644 --- a/servers/nextjs/types/pptx_models.ts +++ b/servers/nextjs/types/pptx_models.ts @@ -304,8 +304,8 @@ export interface PptxPictureBoxModel extends PptxShapeModel { position: PptxPositionModel; margin?: PptxSpacingModel; clip: boolean; - overlay?: string; opacity?: number; + invert?: boolean; border_radius?: number[]; shape?: PptxBoxShapeEnum; object_fit?: PptxObjectFitModel; diff --git a/servers/nextjs/utils/pptx_models_utils.ts b/servers/nextjs/utils/pptx_models_utils.ts index 4d401fea..ff72b341 100644 --- a/servers/nextjs/utils/pptx_models_utils.ts +++ b/servers/nextjs/utils/pptx_models_utils.ts @@ -219,17 +219,11 @@ function convertToPictureBox(element: ElementAttributes): PptxPictureBoxModel { path: element.imageSrc || '' }; - // Set overlay to white if invert is 1 and brightness is 0 - let overlay = element.overlay; - if (element.filters?.invert === 1 && element.filters?.brightness === 0) { - overlay = 'FFFFFF'; - } - return { position, margin: undefined, clip: element.clip ?? true, - overlay, + invert: element.filters?.invert === 1, opacity: element.opacity, border_radius: element.borderRadius ? element.borderRadius.map(r => Math.round(r)) : undefined, shape: element.shape ? (element.shape as PptxBoxShapeEnum) : PptxBoxShapeEnum.RECTANGLE,