laying out images in Word document programatically - wpf

I'm trying to generate a Word document through my application coded in WPF. In that document, I also need to layout few images along with caption as shown in the image below.
All the images are stored in database as base64 string. I'm able to load the images as "BitmapImage" object in the document however not sure how to layout the images as shown in image. Code snippet to load the images in document is as below :
var bookmarks = wordDoc.Bookmarks;
var range = bookmarks["ExternalImage"].Range;
foreach (var image in ExternalImages) // here image is "BitmapImage" object
{
float scaleHeight = (float)250 / (float)image.Image.PixelHeight;
float scaleWidth = (float)250 / (float)image.Image.PixelWidth;
var min = Math.Min(scaleHeight, scaleWidth);
var bitmap = new TransformedBitmap(image, new ScaleTransform(min, min));
System.Windows.Clipboard.SetImage(bitmap);
range.Paste();
}
How can I lay out the images as shown in image above along with caption? Note that I'm not loading images from file but from memory object.

Based on the direction provided by #CindyMeister in comments, following is the working code snippet to layout the images using code :
imageTable = wordDoc.Tables.Add(sel.Range, rows, cols, ref oMissing, ref oMissing);
imageTable.AllowAutoFit = true;
row = 1; col = 1;
foreach (var image in Images)
{
float scaleHeight = (float)475 / (float)image.PixelHeight;
// here 475 is approx image size I want in word document
float scaleWidth = (float)475 / (float)image.PixelWidth;
var min = Math.Min(scaleHeight, scaleWidth);
var bitmap = new TransformedBitmap(image, new ScaleTransform(min, min));
System.Windows.Clipboard.SetImage(bitmap);
//more efficient/faster in C# if you don't "drill down" multiple times to get an object
Word.Cell cel = imageTable.Cell(row, col);
Word.Range rngCell = cel.Range;
Word.Range rngTable = imageTable.Range;
rngCell.Paste();
cel.VerticalAlignment = WdCellVerticalAlignment.wdCellAlignVerticalCenter;
rngCell.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
// set caption below image
rngTable.ParagraphFormat.SpaceAfter = 6;
rngCell.InsertAfter(image.Caption);
rngTable.Font.Name = "Arial Bold";
row++;
}
This code I have posted for reference, only, to let people have some starting point. Any suggestions welcome.

Related

WPF event within a frame stored on a stackpanel

I need to recreate a program similar to whatsapp that can send and receive messages, images videos and audio. I have created a WPF form to show messages that looks like this:
I have a stack panel that contains text bubbles on them. Text messages work fine but if I send an image I want the user to be able to click on the image text bubble and it must become full screen. The image text bubble consists of a label that has a frame in it and then within that frame the image is stored. The label was used since we could resize the label.
However, because the image is done like this dynamically, we cannot seem to register an on-click event on this image bubble. If you have any better ways that we can display the image or how to log this event it would be much appreciated. Here is the method used to add the image.
public void AddMessage_Image(string path, string displayName, int role, string date = "")
{
//Create an image from the path
ImageBrush image = new ImageBrush();
image.ImageSource = new BitmapImage(new Uri(path, UriKind.Absolute));
image.Stretch = Stretch.Uniform;
//Create a frame in which to place the image
Frame fr = new Frame();
fr.Background = image;
fr.MinHeight = 120;
fr.MinWidth = 160;
//Ensure scalabilty of the image
Viewbox vb = new Viewbox();
vb.Child = fr;
vb.Stretch = Stretch.Uniform;
//Place the image in a sizable container
Label lbl = new Label();
lbl.MinHeight = 10;
lbl.MinWidth = 10;
lbl.MaxHeight = 300;
lbl.MaxWidth = 400;
lbl.Content = vb;
if (role == (int) Role.Sender)
lbl.HorizontalAlignment = HorizontalAlignment.Right;
else
lbl.HorizontalAlignment = HorizontalAlignment.Left;
lbl.Background = Brushes.Black;
//Place the image in the chat
chatbox.Children.Add(lbl);
}

How to persist an Image with size, location, and rotation and then restore it?

In WPF, I have an image that is dropped onto an InkCanvas and added as a child:
ImageInfo image_Info = e.Data.GetData(typeof(ImageInfo)) as ImageInfo;
if (image_Info != null)
{
Image image = new Image();
image.Width = image_Info.Width * 4;
image.Stretch = Stretch.Uniform;
image.Source = new BitmapImage(image_Info.Uri);
Point position = e.GetPosition(ic);
InkCanvas.SetLeft(image, position.X);
InkCanvas.SetTop(image, position.Y);
ic.Children.Add(image);
}
Then by way of an adorner, the image is moved and resized. It is then persisted to a database as:
public List<string> Children;
var uiList = ic.Children.Cast<UIElement>().ToList();
foreach (var p in uiList)
{
string uis = System.Windows.Markup.XamlWriter.Save(p);
s.Add(uis);
}
Children = s;
Children then being sent on to the database. The resulting record in the database shows as:
"<Image Source="pack://application:,,,/Images/Female - Front.png" Stretch="Uniform" Width="Auto" InkCanvas.Top="296" InkCanvas.Left="695" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" /> "
There is no reference to the new location, size, or rotation of the image--only its initial drop point. Recreating the image with xmlreader restores the image to its initial drop point and size.
foreach (string s in behavior.Children)
{
var stringReader = new StringReader(s);
var xmlReader = System.Xml.XmlReader.Create(stringReader, new System.Xml.XmlReaderSettings());
Image b = (Image)System.Windows.Markup.XamlReader.Load(xmlReader);
ic.Children.Add(b);
}
(The image source is packed as an application resource).
How can I persist the image with its size, location, and rotation and then restore it?
TIA.
Either you can add additional fields to your DB Table for Size / Location / Rotation and store info there.
Or, you can add these fields together as comma(,) separated and store in Tag field of your Image control. <Image Tag="(120,230);(50,50);(-30)" ... />
You can also save entire manipulated image as byte[] in DB.
Please tell if this solves your problem at hand.

clipped image not visible on Tablet EaselJS + sourceRect used

i am working on a Mobile project (iPad with iOS 8.0.2);
I want to make clipping of my immage in order to display less from it.
When displaying on PC it works perfectly well, while we test it on the tablet the clipped image is not displayed at all.
Do you have any suggestions
this.background = new createjs.Bitmap('some_image.png');
//create a clipping of drawn image!
var dims = this.background.getBounds();
this.background.sourceRect = new createjs.Rectangle(0, 15, dims.width, dims.height);
this.background.x = 248;
this.background.y = 86;
this.stage.addChild(this.background);
I met the same trouble like this.I have given up using Bitmap to clipping the image. I have found another solution ,here is "
easeljs splitting an image into pieces
".Good luck.
I am working out, the code like this:
var img, stage;
function init() {
//wait for the image to load
img = new Image();
img.onload = handleImageLoad;
img.src = "./res/image.png";
}
function handleImageLoad(evt) {
// create a new stage and point it at our canvas:
stage = new createjs.Stage("canvas");
// create a new Bitmap, and slice out one image from the sprite sheet:
var bmp = new createjs.Bitmap(evt.target).set({x:200, y:200});
bmp.sourceRect = new createjs.Rectangle(916, 101, 84, 84);
//x,y,width,height
stage.addChild(bmp);
stage.update();
}
This is the example:
https://github.com/CreateJS/EaselJS/blob/master/examples/Filters_animated.html

Silverlight specific Image shifting to the right

I am generating a set images to form a human body so that I can use for a physics engine.
The images generated are in a specific user control in where I set the dimentions and co-ordinates of each image. That usercontrol is then loaded in another user control but for some reason when the images are loaded, one specific image which I named (rightBicep) is shifting to the right. Here is a screenshot :
alt text http://img193.imageshack.us/img193/592/imageshift.jpg
I illustrated the positions of the images with dotted lines, the green dotted line is refering to where the image should be located, and the red dotted line is where the image is being shown.
The weird thing is the image beneath it (called rightForearm) take's it's LeftPosition from it, and when during debugging they have the exact same leftProperty value. Here's the syntax :
public void generateRightBicep(string imageUrl)
{
rightBicep = new Image();
rightBicep.Name = CharacterName + "rightbicep";
Uri imageUri = new Uri(imageUrl, UriKind.Relative);
LayoutRoot.Children.Add(rightBicep);
rightBicep.Source = new BitmapImage(imageUri);
rightBicep.ImageOpened += new EventHandler<RoutedEventArgs>(bodyPart_ImageOpened);
}
public void rightBicepLoaded()
{
var bi = waitTillImageLoad(rightBicep.Name);
rightBicep.Height = elbowToArmpit + (2 * palm);
rightBicep.Width = ratio(bi.PixelHeight, bi.PixelHeight, rightBicep.Height); // to be determined
Vector2 topVector;
topVector.X = (float)(Convert.ToDouble(torso.GetValue(Canvas.LeftProperty)) - palm);
topVector.Y = (float)(Convert.ToDouble(neck.GetValue(Canvas.TopProperty)) + neck.Height);
if (!faceRight)
{
perspectiveVectorHeight(ref topVector, ref rightBicep, torso.Width);
rightBicep.Width = ratio(bi.PixelHeight, bi.PixelHeight, rightBicep.Height);
}
rightBicep.SetValue(Canvas.LeftProperty, Convert.ToDouble(topVector.X));
rightBicep.SetValue(Canvas.TopProperty, Convert.ToDouble(topVector.Y));
rightBicep.SetValue(Canvas.ZIndexProperty, rightBicepZindex);
generateRightShoulder();
}
public void generateRightForearm(string imageUrl)
{
rightForearm = new Image();
rightForearm.Name = CharacterName + "rightforearm";
Uri imageUri = new Uri(imageUrl, UriKind.Relative);
LayoutRoot.Children.Add(rightForearm);
rightForearm.Source = new BitmapImage(imageUri);
rightForearm.ImageOpened += new EventHandler<RoutedEventArgs>(bodyPart_ImageOpened);
}
public void rightForearmLoaded()
{
var bi = waitTillImageLoad(rightForearm.Name);
rightForearm.Height = (elbowToHandTip - handLength) + palm;
rightForearm.Width = ratio(bi.PixelHeight, bi.PixelWidth, rightForearm.Height);
Vector2 topVector;
if (faceRight)
{
topVector.X = (float)(Convert.ToDouble(rightBicep.GetValue(Canvas.LeftProperty)));
topVector.Y = (float)(Convert.ToDouble(rightBicep.GetValue(Canvas.TopProperty)) + rightBicep.Height - palm);
}
else
{
topVector.X = (float)(Convert.ToDouble(leftBicep.GetValue(Canvas.LeftProperty)));
topVector.Y = (float)(Convert.ToDouble(leftBicep.GetValue(Canvas.TopProperty)) + leftBicep.Height - palm);
perspectiveVectorHeight(ref topVector, ref rightForearm, torso.Width);
rightForearm.Width = ratio(bi.PixelHeight, bi.PixelWidth, rightForearm.Height);
}
rightForearm.SetValue(Canvas.LeftProperty, Convert.ToDouble(topVector.X));
rightForearm.SetValue(Canvas.TopProperty, Convert.ToDouble(topVector.Y));
rightForearm.SetValue(Canvas.ZIndexProperty, rightForearmZIndex);
generateRightElbow();
}
Now all the values I am adding together are a group of doubles I preset, and the property faceRight is to dertmine if the human body is facing right or left to determine where the positions of the body parts (since if the right hand looks on the left hand side when the human body turns the other way).
If you notice the rightforearm is taking the leftproperty of the rightbicep, so technically it should display direcrly underneath which it isn't. I also debugged the user control and both have the left property of -3.
PS. I call the methods rightbicepLoaded and rightforearmLoaded when an event is called when all the imageOpened events all have been triggered.
Any ideas on why this is happening?
Found out why , in my method ratio it should take hieght and width, and I put and i put 2 hieghts instead

Actionscript 3.0 image scaling problems

I am currently building a Flash AS 3.0 application that allows a user to load images into a container, move and scale them and the outputs to a DB. Once the user has uploaded and scaled the images, they are directed to an album viewer which gets the photos out of the DB and puts them into heads. The issue i am having is that once the images go into the viewer, the scaling and positining is not working correctly. The images will scale larger but i cannot shrink them from thrie original size.
I am using the following code to scale the images in the viewer:
headToLoad.width = headWidth;
headToLoad.scaleY > headToLoad.scaleX ? headToLoad.scaleX = headToLoad.scaleY : headToLoad.scaleY = headToLoad.scaleX;
headToLoad.x = xPosition;
headToLoad.y = yPosition;
Any assistance would be great.
Thanks
Justin
I'm not sure what you are trying to do with that 2nd line, but try with this:
headToLoad.width = headWidth;
headToLoad.scaleY = headToLoad.scaleX;
The function does what it should do.
If you want a something that would constrict the size of a loaded image to a maximum width and height, mantaining the ratio, you could use something like this.
import flash.display.*;
import flash.net.URLRequest;
import flash.events.Event;
var maxWidth = 200;
var maxHeight = 300;
var headToLoad:Loader = new Loader();
headToLoad.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadCompleted);
addChild(headToLoad);
headToLoad.load(new URLRequest("picture.jpg"));
function onLoadCompleted(evt:Event) {
var head = evt.target.loader; // or evt.target.content
head.width = maxWidth;
head.scaleY = head.scaleX;
if (head.height > maxHeight) {
head.height = maxHeight;
head.scaleX = head.scaleY;
}
head.x = 100;
head.y = 100;
}

Resources