public void makeSampleImage(FreeImageBitmap bitmap) { if (LoadLogo != null) { using (FreeImageBitmap logo = LoadLogo()) { float sizeRatio = (float)bitmap.Width / logo.Width; int finalLogoWidth = (int)(logo.Width * sizeRatio); int finalLogoHeight = (int)(logo.Height * sizeRatio); int currentY = 0; int imageHeight = bitmap.Height; bitmap.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP); logo.Rescale(finalLogoWidth, finalLogoHeight, FREE_IMAGE_FILTER.FILTER_BILINEAR); while (currentY < imageHeight) { int sectionHeight = logo.Height; if (currentY + sectionHeight > imageHeight) { sectionHeight = imageHeight - currentY; } using (FreeImageBitmap section = bitmap.Copy(0, currentY, logo.Width, currentY + sectionHeight)) { using (FreeImageBitmap logoComposite = logo.Copy(0, 0, logo.Width, sectionHeight)) { logoComposite.Composite(false, null, section); bitmap.Paste(logoComposite, 0, currentY, int.MaxValue); currentY += finalLogoHeight; } } } } } }
public void writeText(FreeImageBitmap bitmap, string p, int fontSize) { p = p.Replace("\n", "<br/>"); int width = Math.Min(bitmap.Width, 2048); int height = Math.Min(bitmap.Height, 256); ImageBox imageBox = (ImageBox)Gui.Instance.createWidgetT("ImageBox", "ImageBox", 0, 0, width, height, Align.Default, "Overlapped", "TempImageBox"); RocketWidget rocketWidget = null; try { imageBox.Visible = false; rocketWidget = new RocketWidget(imageBox, true); var cornerColor = Engine.Color.FromARGB(bitmap.GetPixel(0, 0).ToArgb()); rocketWidget.resized(); StringBuilder sb = new StringBuilder(); sb.AppendFormat(DocumentStart, cornerColor.ToHexString(), fontSize); sb.AppendFormat("<p>{0}</p>", p); sb.Append(DocumentEnd); var resourceLoader = new RocketAssemblyResourceLoader(this.GetType().Assembly); RocketInterface.Instance.FileInterface.addExtension(resourceLoader); var document = rocketWidget.Context.LoadDocumentFromMemory(sb.ToString()); if (document != null) { document.Show(ElementDocument.FocusFlags.NONE); } RocketInterface.Instance.FileInterface.removeExtension(resourceLoader); using (FreeImageBitmap copyrightBitmap = new FreeImageBitmap(imageBox.Width, imageBox.Height, PixelFormat.Format32bppArgb)) { rocketWidget.writeToGraphics(copyrightBitmap, new Rectangle(0, 0, copyrightBitmap.Width, copyrightBitmap.Height)); using (FreeImageBitmap background = bitmap.Copy(0, 0, Math.Min(copyrightBitmap.Width, bitmap.Width), Math.Min(copyrightBitmap.Height, bitmap.Height))) { background.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP); copyrightBitmap.Composite(false, null, background); bitmap.Paste(copyrightBitmap, 0, 0, int.MaxValue); } } } finally { //Using block does not work (wtf?), dispose manually if (rocketWidget != null) { rocketWidget.Dispose(); } Gui.Instance.destroyWidget(imageBox); } }
public static void Combine(ImageFile[] images, string outputFile, string mapFile) { // Find max width and total height var maxWidth = 0; var maxHeight = 0; var totalHeight = 0; foreach (var image in images) { totalHeight += image.Image.Height; if (image.Image.Width > maxWidth) maxWidth = image.Image.Width; if (image.Image.Height > maxHeight) maxHeight = image.Image.Height; } Console.WriteLine(string.Format("Number of images: {0}, total height: {1}px, width: {2}", images.Length, totalHeight, maxWidth)); // Create the actual sprite var currentY = 0; const int currentX = 0; var surface = new FreeImageBitmap(maxWidth, totalHeight); foreach (var image in images) { var freeImage = GetFreeImage(image); surface.Paste(freeImage, currentX, currentY, 0); currentY += image.Image.Height; image.X = currentX; image.Y = currentY; Console.WriteLine("{0} copied to {1}, {2}", image.Name, image.X, image.Y); } Console.WriteLine("Writing sprite: " + outputFile); using (var stream = File.OpenWrite(outputFile)) { surface.Save(stream, FREE_IMAGE_FORMAT.FIF_PNG); } Console.WriteLine("Writing sprite map: " + mapFile); using (var writer = File.CreateText(mapFile)) { foreach (var image in images) { writer.WriteLine(image); image.Dispose(); } } }
private IEnumerable <IdleStatus> gridRender(int width, int height, int backBufferWidth, int backBufferHeight, int aaMode, RenderTexture renderTexture, Camera camera, Camera backgroundCamera, bool transparentBG, Engine.Color bgColor, Action <FreeImageBitmap> renderingCompletedCallback) { float originalLeft, originalRight, originalTop, originalBottom; camera.getFrustumExtents(out originalLeft, out originalRight, out originalTop, out originalBottom); int imageCountWidth = width % backBufferWidth == 0 ? width / backBufferWidth : width / backBufferWidth + 1; int imageCountHeight = height % backBufferHeight == 0 ? height / backBufferHeight : height / backBufferHeight + 1; float gridStepHoriz = (originalRight * 2) / imageCountWidth; float gridStepVert = (originalTop * 2) / imageCountHeight; float bgOriginalLeft = 0, bgOriginalRight = 0, bgOriginalTop = 0, bgOriginalBottom = 0, bgGridStepHoriz = 0, bgGridStepVert = 0; if (backgroundCamera != null) { backgroundCamera.getFrustumExtents(out bgOriginalLeft, out bgOriginalRight, out bgOriginalTop, out bgOriginalBottom); bgGridStepHoriz = (bgOriginalRight * 2) / imageCountWidth; bgGridStepVert = (bgOriginalTop * 2) / imageCountHeight; } int imageStepHoriz = backBufferWidth; int imageStepVert = backBufferHeight; int finalWidth = width / aaMode; int finalHeight = height / aaMode; int imageStepHorizSmall = finalWidth / imageCountWidth; int imageStepVertSmall = finalHeight / imageCountHeight; float left, right, top, bottom; float bgLeft, bgRight, bgTop, bgBottom; int totalSS = imageCountWidth * imageCountHeight; String updateString = "Rendering piece {0} of " + totalSS; OgrePlugin.PixelFormat format = OgrePlugin.PixelFormat.PF_A8R8G8B8; FreeImageAPI.PixelFormat bitmapFormat = FreeImageAPI.PixelFormat.Format32bppRgb; if (transparentBG) { bitmapFormat = FreeImageAPI.PixelFormat.Format32bppArgb; } Rectangle destRect = new Rectangle(); Rectangle srcRect = new Rectangle(0, 0, imageStepHoriz, imageStepVert); FreeImageBitmap fullBitmap = new FreeImageBitmap(finalWidth, finalHeight, bitmapFormat); using (FreeImageBitmap pieceBitmap = new FreeImageBitmap(imageStepHoriz, imageStepVert, bitmapFormat)) { bool aaOn = aaMode > 1; Rectangle scalarRectangle = new Rectangle(); if (aaOn) { scalarRectangle = new Rectangle(0, 0, imageStepHorizSmall, imageStepVertSmall); } for (int i = 0; i < totalSS; ++i) { int y = i / imageCountWidth; int x = i - y * imageCountWidth; left = originalLeft + gridStepHoriz * x; right = left + gridStepHoriz; top = originalTop - gridStepVert * y; bottom = top - gridStepVert; camera.setFrustumExtents(left, right, top, bottom); if (backgroundCamera != null) { bgLeft = bgOriginalLeft + bgGridStepHoriz * x; bgRight = bgLeft + bgGridStepHoriz; bgTop = bgOriginalTop - bgGridStepVert * y; bgBottom = bgTop - bgGridStepVert; backgroundCamera.setFrustumExtents(bgLeft, bgRight, bgTop, bgBottom); } Root.getSingleton().clearEventTimes(); renderTexture.getViewport(0).clear(FrameBufferType.FBT_COLOUR | FrameBufferType.FBT_DEPTH | FrameBufferType.FBT_STENCIL, bgColor); renderTexture.update(); pieceBitmap.copyFromRenderTarget(renderTexture, format); destRect.X = x * imageStepHorizSmall; destRect.Y = y * imageStepVertSmall; destRect.Width = imageStepHorizSmall; destRect.Height = imageStepVertSmall; if (aaOn) { using (FreeImageBitmap scaled = new FreeImageBitmap(pieceBitmap)) { scaled.Rescale(scalarRectangle.Width, scalarRectangle.Height, FREE_IMAGE_FILTER.FILTER_BILINEAR); fullBitmap.Paste(scaled, destRect.X, destRect.Y, int.MaxValue); } } else { fullBitmap.Paste(pieceBitmap, destRect.X, destRect.Y, int.MaxValue); } if (imageRendererProgress != null) { imageRendererProgress.update((uint)(((float)(i + 1) / totalSS) * 100.0f), String.Format(updateString, i + 1)); if (imageRendererProgress.Cancel) { break; } } yield return(IdleStatus.Ok); } } renderTexture.getViewport(0).setOverlaysEnabled(true); renderingCompletedCallback(fullBitmap); yield break; }
private IEnumerable <IdleStatus> createRender(int finalWidth, int finalHeight, int aaMode, bool showWatermark, bool transparentBG, Engine.Color backColor, Camera cloneCamera, Vector3 position, Vector3 lookAt, float minNearDistance, float nearPlaneWorld, float nearFarLength, ImageRendererProperties properties, Action <FreeImageBitmap> renderingCompletedCallback) { FreeImageBitmap bitmap = null; OgreSceneManager sceneManager = controller.CurrentScene.getDefaultSubScene().getSimElementManager <OgreSceneManager>(); if (sceneManager != null) { bool doGridRender; int backBufferWidth; int backBufferHeight; using (TexturePtr texture = createOgreTexture(finalWidth, finalHeight, aaMode, out doGridRender, out backBufferWidth, out backBufferHeight)) { if (texture != null) { using (HardwarePixelBufferSharedPtr pixelBuffer = texture.Value.getBuffer()) { RenderTexture renderTexture = pixelBuffer.Value.getRenderTarget(); Camera camera = sceneManager.SceneManager.createCamera("__PictureCamera"); camera.setLodBias(cloneCamera.getLodBias()); camera.setUseRenderingDistance(cloneCamera.getUseRenderingDistance()); camera.setNearClipDistance(cloneCamera.getNearClipDistance()); camera.setFarClipDistance(cloneCamera.getFarClipDistance()); camera.setPolygonMode(cloneCamera.getPolygonMode()); camera.setRenderingDistance(cloneCamera.getRenderingDistance()); camera.setProjectionType(cloneCamera.getProjectionType()); camera.setFOVy(cloneCamera.getFOVy()); camera.setAutoAspectRatio(false); camera.setAspectRatio((float)finalWidth / finalHeight); SceneNode node = sceneManager.SceneManager.createSceneNode("__PictureCameraNode"); node.attachObject(camera); node.setPosition(position); sceneManager.SceneManager.getRootSceneNode().addChild(node); camera.lookAt(lookAt); Viewport viewport = renderTexture.addViewport(camera, 1, 0.0f, 0.0f, 1.0f, 1.0f); if (properties.UseIncludePoint) { Matrix4x4 viewMatrix = camera.getViewMatrix(); Matrix4x4 projectionMatrix = camera.getProjectionMatrix(); float aspect = camera.getAspectRatio(); float fovy = camera.getFOVy() * 0.5f; float distance = SceneViewWindow.computeOffsetToIncludePoint(viewMatrix, projectionMatrix, properties.IncludePoint, aspect, fovy); Vector3 direction = (position - lookAt).normalized(); node.setPosition(position - (direction * distance)); camera.lookAt(lookAt); } if (transparentBG) { backColor.a = 0.0f; } ViewportBackground bgViewport = null; if (background != null) { bgViewport = new ViewportBackground("ImageRenderer", 0, background, renderTexture, false); bgViewport.BackgroundColor = backColor; bgViewport.Camera.setAutoAspectRatio(false); bgViewport.Camera.setAspectRatio((float)finalWidth / finalHeight); } viewport.setBackgroundColor(backColor); viewport.setOverlaysEnabled(false); viewport.setClearEveryFrame(false); if (properties.CustomizeCameraPosition != null) { properties.CustomizeCameraPosition(camera, viewport); } float near = CameraPositioner.computeNearClipDistance(camera.getDerivedPosition().length(), minNearDistance, nearPlaneWorld); camera.setNearClipDistance(near); camera.setFarClipDistance(near + nearFarLength); if (doGridRender) { IEnumerable <IdleStatus> process = gridRender(finalWidth * aaMode, finalHeight * aaMode, backBufferWidth, backBufferHeight, aaMode, renderTexture, camera, bgViewport != null ? bgViewport.Camera : null, transparentBG, backColor, (product) => { bitmap = product; }); foreach (IdleStatus idleStatus in process) { yield return(idleStatus); } } else { bitmap = simpleRender(backBufferWidth, backBufferHeight, aaMode, transparentBG, backColor, renderTexture); } if (showWatermark && LoadLogo != null) { using (FreeImageBitmap logo = LoadLogo()) { float imageFinalHeight = bitmap.Height * 0.0447f; float scale = imageFinalHeight / logo.Height; float imageFinalWidth = logo.Width * scale; if (imageFinalWidth > bitmap.Width) { imageFinalWidth = bitmap.Width; scale = imageFinalWidth / logo.Width; imageFinalHeight = logo.Height * scale; } logo.Rescale((int)imageFinalWidth, (int)imageFinalHeight, FREE_IMAGE_FILTER.FILTER_BILINEAR); //Have to composite the logo image first. using (FreeImageBitmap fullImageCorner = bitmap.Copy(0, bitmap.Height - (int)imageFinalHeight, (int)imageFinalWidth, bitmap.Height)) { fullImageCorner.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP); logo.Composite(false, null, fullImageCorner); } bitmap.Paste(logo, 0, bitmap.Height - (int)imageFinalHeight, int.MaxValue); } } renderTexture.destroyViewport(viewport); if (bgViewport != null) { bgViewport.Dispose(); } sceneManager.SceneManager.getRootSceneNode().removeChild(node); sceneManager.SceneManager.destroySceneNode(node); sceneManager.SceneManager.destroyCamera(camera); TextureManager.getInstance().remove(texture); } } else { //An error making the render texture. Log it and return the error image. Log.Error("Could not render image. Returning placeholder image. Reason: Could not create valid render to texture target."); bitmap = new FreeImageBitmap(finalWidth, finalHeight); bitmap.FillBackground(new RGBQUAD() { rgbRed = 255 }); } } } renderingCompletedCallback(bitmap); yield break; }
public void updateThumbnail(bool forceUpdateSceneThumb = false) { Dictionary <RmlEditorViewInfo, LayoutContainer> layoutPositions = new Dictionary <RmlEditorViewInfo, LayoutContainer>(); if (slideEditorController.ResourceProvider != null) { //Setup a LayoutChain to mimic the main one. LayoutChain layoutChain = new LayoutChain(); layoutChain.addLink(new PopupAreaChainLink(GUILocationNames.ContentAreaPopup), true); layoutChain.addLink(new BorderLayoutNoAnimationChainLink(GUILocationNames.ContentArea), true); IntSize2 thumbTotalSize = new IntSize2(SlideImageManager.ThumbWidth, SlideImageManager.ThumbHeight); FreeImageBitmap thumb = slideEditorController.SlideImageManager.createThumbBitmap(slide); layoutChain.SuppressLayout = true; LayoutContainer sceneContainer = new NullLayoutContainer(thumbTotalSize); layoutChain.addContainer(new BorderLayoutElementName(GUILocationNames.ContentArea, BorderLayoutLocations.Center), sceneContainer, null); foreach (var editor in rmlEditors.Values) { if (editor.Component != null) { float sizeRatio = (float)SlideImageManager.ThumbHeight / editor.Component.ViewHost.Container.RigidParentWorkingSize.Height; IntSize2 size = (IntSize2)(editor.Component.ViewHost.Container.DesiredSize * sizeRatio); NullLayoutContainer container = new NullLayoutContainer(size); layoutPositions.Add(editor, container); layoutChain.addContainer(editor.View.ElementName, container, null); } } layoutChain.SuppressLayout = false; layoutChain.WorkingSize = thumbTotalSize; layoutChain.Location = new IntVector2(0, 0); layoutChain.layout(); //Render thumbnail, Start with the scene IntVector2 sceneThumbPosition = sceneContainer.Location; String sceneThumbFile = slide.SceneThumbName; if (forceUpdateSceneThumb) { slideEditorController.SlideImageManager.addUnsavedSceneThumb(slide, renderSceneThumbnail()); } SceneThumbInfo sceneThumbInfo = slideEditorController.SlideImageManager.loadThumbSceneBitmap(slide, renderSceneThumbnail); IntSize2 centerSize = sceneContainer.WorkingSize; RectangleF destRect = new RectangleF(sceneThumbPosition.x, sceneThumbPosition.y, centerSize.Width, centerSize.Height); thumb.FillBackground(new RGBQUAD(FreeImageAPI.Color.FromArgb(sceneThumbInfo.Color.toARGB()))); int requiredWidth = (sceneThumbInfo.SceneThumb.Width - ((sceneThumbInfo.SceneThumb.Width - sceneThumbInfo.IncludeX) * 2)); int requiredHeight = (sceneThumbInfo.SceneThumb.Height - (sceneThumbInfo.IncludeY * 2)); int sceneThumbWidth = sceneThumbInfo.SceneThumb.Width; int sceneThumbHeight = sceneThumbInfo.SceneThumb.Height; int sceneThumbHalfWidth = sceneThumbWidth / 2; int sceneThumbHalfHeight = sceneThumbHeight / 2; float requiredHeightWidthRatio = (float)requiredHeight / requiredWidth; float centerHeightWidthRatio = (float)centerSize.Height / centerSize.Width; float srcWidth = requiredWidth; float srcHeight = requiredHeight; if (requiredHeightWidthRatio < centerHeightWidthRatio) //Compare ratios between our source required area and the destination { //Use the full required width, add height from source image //Convert the center size to the same size ratio as the required size float sizeRatio = (float)requiredWidth / centerSize.Width; srcHeight = centerSize.Height * sizeRatio; if (srcHeight > sceneThumbHeight) //Stretch out the image as much as possible, limiting by the size of the scene thumb if needed. { srcHeight = sceneThumbHeight; } float destHeight = srcHeight / sizeRatio; destRect = new RectangleF(destRect.Left, destRect.Height / 2 + destRect.Top - destHeight / 2, destRect.Width, destHeight); //Make a dest rect that takes as much image as it can } else { //Use the full required height, add width from source image float sizeRatio = (float)requiredHeight / centerSize.Height; srcWidth = centerSize.Width * sizeRatio; if (srcWidth > sceneThumbWidth) { srcWidth = sceneThumbWidth; } float destWidth = srcWidth / sizeRatio; destRect = new RectangleF(destRect.Width / 2 + destRect.Left - destWidth / 2, destRect.Top, destWidth, destRect.Height); } RectangleF srcRect = new RectangleF(sceneThumbHalfWidth - srcWidth / 2, sceneThumbHalfHeight - srcHeight / 2, srcWidth, srcHeight); using (FreeImageBitmap resizedSceneThumb = sceneThumbInfo.SceneThumb.Copy((int)srcRect.X, (int)srcRect.Y, (int)srcRect.Right, (int)srcRect.Bottom)) { resizedSceneThumb.Rescale((int)destRect.Width, (int)destRect.Height, FREE_IMAGE_FILTER.FILTER_BILINEAR); thumb.Paste(resizedSceneThumb, (int)destRect.X, (int)destRect.Y, int.MaxValue); } //Render all panels foreach (var editor in rmlEditors.Values) { if (editor.Component != null) { LayoutContainer container; if (layoutPositions.TryGetValue(editor, out container)) { Rectangle panelThumbPos = new Rectangle(container.Location.x, container.Location.y, container.WorkingSize.Width, container.WorkingSize.Height); editor.Component.writeToGraphics(thumb, panelThumbPos); } } } slideEditorController.SlideImageManager.thumbnailUpdated(slide); } }
/// <summary> /// Write to the given graphics, if the widget texture is not large enough it will be /// resized temporarily and then sized back. So be careful with large destrects. /// </summary> /// <param name="g"></param> /// <param name="destRect"></param> public void writeToGraphics(FreeImageBitmap g, Rectangle destRect) { bool changedSize = false; IntSize2 originalSize = new IntSize2(imageBox.Width, imageBox.Height); float cropRatio = (float)imageBox.Width / destRect.Width; Rectangle srcRect = new Rectangle(0, 0, imageBox.Width, (int)(destRect.Height * cropRatio)); //Make sure the source image is large enough, if not resize. if (originalSize.Width < srcRect.Width || originalSize.Height < srcRect.Height) { imageBox.setSize(srcRect.Width, srcRect.Height); changedSize = true; resized(); renderTexture.update(); } else if (renderOneFrame) { renderTexture.update(); } using (FreeImageBitmap fullBitmap = new FreeImageBitmap(currentTextureWidth, currentTextureHeight, BitmapFormat)) { fullBitmap.copyFromRenderTarget(renderTexture, ogreTextureFormat); //Remove alpha //BitmapDataExtensions.SetAlpha(bmpData, 255); if (srcRect.Height > fullBitmap.Height) { srcRect.Height = fullBitmap.Height; } using (FreeImageBitmap cropped = fullBitmap.Copy(srcRect)) { if (cropped != null) { cropped.Rescale(destRect.Width, destRect.Height, FREE_IMAGE_FILTER.FILTER_BILINEAR); if (ogreTextureFormat == OgrePlugin.PixelFormat.PF_X8R8G8B8) { //Use the api to set the alpha channel to 255, this makes sure we dont carry over the x8 channel from ogre using (var alpha = cropped.GetChannel(FREE_IMAGE_COLOR_CHANNEL.FICC_ALPHA)) { alpha.FillBackground(new RGBQUAD(new FreeImageAPI.Color() { R = 255, G = 255, B = 255, A = 255 })); cropped.SetChannel(alpha, FREE_IMAGE_COLOR_CHANNEL.FICC_ALPHA); } } g.Paste(cropped, destRect.X, destRect.Y, int.MaxValue); } } } if (changedSize) { imageBox.setSize(originalSize.Width, originalSize.Height); resized(); renderTexture.update(); } }