wordpress hit counter
Re: Disable image streching in placeholders - .Net - Development Tools - OpenXML Developer

Re: Disable image streching in placeholders

Development Tools

Discussions about working with Open XML using a wide range of development tools

Disable image streching in placeholders

  • rated by 0 users
  • This post has 10 Replies |
  • 6 Followers
  • Hi!

    I create a presentation. On my slide I have placeholders and you can add images, graphs, or simple text contents to it. The content now always fill the placeholder which is a good thing when the content is a text.

    But when the content is an image it's streched and it doesn't look good. How can i keep  its original size-ratio?

     

    right now my code looks like this:

      Picture picture1 = new Picture();
    
                NonVisualPictureProperties nonVisualPictureProperties1 = new NonVisualPictureProperties();
                NonVisualDrawingProperties nonVisualDrawingProperties3 = new NonVisualDrawingProperties() { Id = (UInt32Value)5U, Name = psi.PlaceHolderName, Description = string.Format("slide{0}.jpg", lastPictureId) };
    
                NonVisualPictureDrawingProperties nonVisualPictureDrawingProperties1 = new NonVisualPictureDrawingProperties();
                A.PictureLocks pictureLocks1 = new A.PictureLocks() { NoGrouping = true, NoChangeAspect = true };
    
                nonVisualPictureDrawingProperties1.Append(pictureLocks1);
    
                ApplicationNonVisualDrawingProperties applicationNonVisualDrawingProperties3 = new ApplicationNonVisualDrawingProperties();
                PlaceholderShape placeholderShape2 = new PlaceholderShape() { Type = PlaceholderValues.Picture, Index = (UInt32Value)1U };
    
                applicationNonVisualDrawingProperties3.Append(placeholderShape2);
    
                nonVisualPictureProperties1.Append(nonVisualDrawingProperties3);
                nonVisualPictureProperties1.Append(nonVisualPictureDrawingProperties1);
                nonVisualPictureProperties1.Append(applicationNonVisualDrawingProperties3);
    
                BlipFill blipFill1 = new BlipFill();
    
                A.Blip blip1 = new A.Blip() { Embed = pictureName };
    
                A.BlipExtensionList blipExtensionList1 = new A.BlipExtensionList();
    
                A.BlipExtension blipExtension1 = new A.BlipExtension() { Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}" };
    
                A14.UseLocalDpi useLocalDpi1 = new A14.UseLocalDpi() { Val = false };
                useLocalDpi1.AddNamespaceDeclaration("a14", "http://schemas.microsoft.com/office/drawing/2010/main");
    
                blipExtension1.Append(useLocalDpi1);
    
                blipExtensionList1.Append(blipExtension1);
    
                blip1.Append(blipExtensionList1);
                A.SourceRectangle sourceRectangle1 = new A.SourceRectangle();
    
                A.Stretch stretch1 = new A.Stretch();
                A.FillRectangle fillRectangle1 = new A.FillRectangle();
                A.FillToRectangle fillToRectangle1 = new A.FillToRectangle();
                stretch1.Append(fillRectangle1);            
    
                blipFill1.Append(blip1);
                blipFill1.Append(sourceRectangle1);
                blipFill1.Append(stretch1);
                ShapeProperties shapeProperties2 = new ShapeProperties();
    
                A.Transform2D transform2D2 = new A.Transform2D();
    
                A.Offset offset1 = new A.Offset() { X = Convert.ToInt64(phf.x), Y = Convert.ToInt64(phf.y) };
                A.Extents extents1 = new A.Extents() { Cx = Convert.ToInt64(phf.cx), Cy = Convert.ToInt64(phf.cy) };
    
    
                transform2D2.Append(offset1);
                transform2D2.Append(extents1);
    
                A.PresetGeometry presetGeometry2 = new A.PresetGeometry() { Preset = A.ShapeTypeValues.Rectangle };
                A.AdjustValueList adjustValueList2 = new A.AdjustValueList();
    
                presetGeometry2.Append(adjustValueList2);
    
                shapeProperties2.Append(transform2D2);
                shapeProperties2.Append(presetGeometry2);
    
                picture1.Append(nonVisualPictureProperties1);
                picture1.Append(blipFill1);
                picture1.Append(shapeProperties2);
    
                shapeTree1.Append(picture1);

    Thank you in advance!

     

    Zoli

  • Hi Zoli,

              You have to modify the transform2D2 -> Extents (Cx &Cy). Cx is the width of the image and Cy is the height. These values are in EMU. So you need to convert the image Height and Width (which will be in pixels) to EMU. Replace transform2D2 code with this.

               A.Transform2D transform2D2 = new A.Transform2D();

               A.Offset offset1 = new A.Offset() { X = Convert.ToInt64(phf.x), Y = Convert.ToInt64(phf.y) };

               A.Extents extents1 = new A.Extents() { Cx = Convert.ToInt64(phf.cx), Cy = Convert.ToInt64(phf.cy) };

               transform2D2.Append(offset1);

               transform2D2.Append(extents1);

                   int imgWidth = 0, imgHeight = 0;

                   Int64 actualWidthEmu = 0, actualHeightEmu = 0;

                   // set default values to imgWidth, imgHeight, actualWidthEmu and actualHeightEmu

                   ImageHelper.InitializeDefaultValues(ref imgWidth, ref imgHeight, ref actualWidthEmu, ref actualHeightEmu);

                   ImageHelper.SetActualSize(imageFile, imgWidth, imgHeight, ref actualWidthEmu, ref actualHeightEmu);

                   transform2D2.Transform2D.Extents.Cx = actualWidthEmu;

                   transform2D2.Transform2D.Extents.Cy = actualHeightEmu;

    ...........

    public class ImageHelper

       {

    internal static void InitializeDefaultValues(ref int imgWidth, ref int imgHeight, ref long actualWidthEmu, ref long actualHeightEmu)

           {

               // set default values

               imgWidth = ImageBenchmarks.WidthInPixel;

               imgHeight = ImageBenchmarks.HeightInPixel;

               actualWidthEmu = ImageBenchmarks.WidthInEmu;

               actualHeightEmu = ImageBenchmarks.HeightInEmu;

           }

    internal static void SetActualSize(string imageFile, int imgWidth, int imgHeight, ref long actualWidthEmu, ref long actualHeightEmu)

           {

               Bitmap img = (Bitmap)Image.FromFile(imageFile);

               imgWidth = (img.Width >= ImageBenchmarks.MinWidth && img.Width <= ImageBenchmarks.MaxWidth) ? img.Width : imgWidth;

               imgHeight = (img.Height >= ImageBenchmarks.MinHeight && img.Height <= ImageBenchmarks.MaxHeight) ? img.Height : imgHeight;

               // calculate actual width in EMU

               actualWidthEmu = (ImageBenchmarks.WidthInEmu * imgWidth) / ImageBenchmarks.WidthInPixel;

               // calculate actual height in EMU

               actualHeightEmu = (ImageBenchmarks.HeightInEmu * imgHeight) / ImageBenchmarks.HeightInPixel;

               img.Dispose();

           }

    }

    public struct ImageBenchmarks

       {

           // minimum

           public const int MinWidth = 16;

           public const int MinHeight = 16;

           // maximum

           public const int MaxWidth = 960;

           public const int MaxHeight = 720;

           // default

           public const int WidthInPixel = 96;

           public const int HeightInPixel = 80;

           // default EMU

           public const int WidthInEmu = 914400;

           public const int HeightInEmu = 749300;        

       }

  • Hi! thank you for you help! It works, however the images are much smaller than they supposed to be. I would like them to fill their placeholder as much as possible without losing its size-ratio

  • Keep the placeholder as small as possible (0.25" X 0.2"). If the image is larger in, that gets expanded automatically.

  • I actually managed to write a custom method to adjust a piucture to fix into it's placeholder with the biggest size without losing its side-ratio, i thought i'd share the code so it might help others:

    private static PlaceHolderFormat ComputeImageParamaters(byte[] image, PlaceHolderFormat PlaceHolderParams)

           {

               PlaceHolderFormat returnformat = new PlaceHolderFormat();

               MemoryStream ms = new MemoryStream(image);                        

               Bitmap img = (Bitmap)Image.FromStream(ms);

               long PicSizeXInEMU = (long)img.Width * (long)((float)914400 / img.HorizontalResolution);

               long PicSizeYInEMU = (long)img.Height * (long)((float)914400 / img.VerticalResolution);

               double PlaceHolderToPicXRatio = PlaceHolderParams.cx / img.Width;

               double PlaceHolderToPicYRatio = PlaceHolderParams.cy / img.Height;    

               double t_RatioOfPlaceHolderSides = (double)PlaceHolderParams.cx / PlaceHolderParams.cy;

               double t_RatioOfPictureSideSides = (double)img.Width / img.Height;

               long NewPicSizeXInEMU;

               long NewPicSizeYInEMU;

               if (t_RatioOfPlaceHolderSides < t_RatioOfPictureSideSides)

               {

                   //x has to be identical

                   NewPicSizeXInEMU = PlaceHolderParams.cx;

                   double ratio = (double)PlaceHolderParams.cx / PicSizeXInEMU;

                   NewPicSizeYInEMU = Convert.ToInt64(PicSizeYInEMU * ratio);

               }

               else

               {

                   //y has to be identical

                   NewPicSizeYInEMU = PlaceHolderParams.cy;

                   double ratio = (double)PlaceHolderParams.cy / PicSizeYInEMU;

                   NewPicSizeXInEMU = Convert.ToInt64(PicSizeXInEMU * ratio);

               }

               returnformat.cx = Convert.ToUInt32(NewPicSizeXInEMU);

               returnformat.cy = Convert.ToUInt32(NewPicSizeYInEMU);

               returnformat.x = (PlaceHolderParams.cx - returnformat.cx) / 2 + PlaceHolderParams.x;

               returnformat.y = (PlaceHolderParams.cy - returnformat.cy) / 2 + PlaceHolderParams.y;

               return returnformat;

           }

     public class PlaceHolderFormat

       {

           public uint x  { get; set; }

           public uint y  { get; set; }

           public uint cx { get; set; }

           public uint cy { get; set; }

       }

    use it like this:

    A.Transform2D transform2D2 = new A.Transform2D();

               PlaceHolderFormat newPhf =  ComputeImageParamaters(Picture, OriginalPlaceHolder);

               A.Offset offset1 = new A.Offset() { X = Convert.ToInt64(newPhf.x), Y = Convert.ToInt64(newPhf.y) };

               A.Extents extents1 = new A.Extents() { Cx = Convert.ToInt64(newPhf.cx), Cy = Convert.ToInt64(newPhf.cy) };

               transform2D2.Append(offset1);

               transform2D2.Append(extents1);

  • I actually managed to write a custom method to adjust a piucture to fix into it's placeholder with the biggest size without losing its side-ratio, i thought i'd share the code so it might help others:

    private static PlaceHolderFormat ComputeImageParamaters(byte[] image, PlaceHolderFormat PlaceHolderParams)

           {

               PlaceHolderFormat returnformat = new PlaceHolderFormat();

               MemoryStream ms = new MemoryStream(image);                        

               Bitmap img = (Bitmap)Image.FromStream(ms);

               long PicSizeXInEMU = (long)img.Width * (long)((float)914400 / img.HorizontalResolution);

               long PicSizeYInEMU = (long)img.Height * (long)((float)914400 / img.VerticalResolution);

               double PlaceHolderToPicXRatio = PlaceHolderParams.cx / img.Width;

               double PlaceHolderToPicYRatio = PlaceHolderParams.cy / img.Height;    

               double t_RatioOfPlaceHolderSides = (double)PlaceHolderParams.cx / PlaceHolderParams.cy;

               double t_RatioOfPictureSideSides = (double)img.Width / img.Height;

               long NewPicSizeXInEMU;

               long NewPicSizeYInEMU;

               if (t_RatioOfPlaceHolderSides < t_RatioOfPictureSideSides)

               {

                   //x has to be identical

                   NewPicSizeXInEMU = PlaceHolderParams.cx;

                   double ratio = (double)PlaceHolderParams.cx / PicSizeXInEMU;

                   NewPicSizeYInEMU = Convert.ToInt64(PicSizeYInEMU * ratio);

               }

               else

               {

                   //y has to be identical

                   NewPicSizeYInEMU = PlaceHolderParams.cy;

                   double ratio = (double)PlaceHolderParams.cy / PicSizeYInEMU;

                   NewPicSizeXInEMU = Convert.ToInt64(PicSizeXInEMU * ratio);

               }

               returnformat.cx = Convert.ToUInt32(NewPicSizeXInEMU);

               returnformat.cy = Convert.ToUInt32(NewPicSizeYInEMU);

               returnformat.x = (PlaceHolderParams.cx - returnformat.cx) / 2 + PlaceHolderParams.x;

               returnformat.y = (PlaceHolderParams.cy - returnformat.cy) / 2 + PlaceHolderParams.y;

               return returnformat;

           }

     public class PlaceHolderFormat

       {

           public uint x  { get; set; }

           public uint y  { get; set; }

           public uint cx { get; set; }

           public uint cy { get; set; }

       }

    use it like this:

    A.Transform2D transform2D2 = new A.Transform2D();

               PlaceHolderFormat newPhf =  ComputeImageParamaters(Picture, OriginalPlaceHolder);

               A.Offset offset1 = new A.Offset() { X = Convert.ToInt64(newPhf.x), Y = Convert.ToInt64(newPhf.y) };

               A.Extents extents1 = new A.Extents() { Cx = Convert.ToInt64(newPhf.cx), Cy = Convert.ToInt64(newPhf.cy) };

               transform2D2.Append(offset1);

               transform2D2.Append(extents1);

  • Hi. Is there any way I can set the widtth and height of a Image Cell? I've tried almost anything. I use this Function:

    DocumentFormat.OpenXml.Drawing.TableCell tc = new DocumentFormat.OpenXml.Drawing.TableCell(

                   new DocumentFormat.OpenXml.Drawing.TextBody(

                       new DocumentFormat.OpenXml.Drawing.BodyProperties(),

                       new DocumentFormat.OpenXml.Drawing.Paragraph()),

                   new DocumentFormat.OpenXml.Drawing.TableCellProperties(

                       new DocumentFormat.OpenXml.Drawing.BlipFill(

                           new DocumentFormat.OpenXml.Drawing.Blip() { Embed = relId },

                               new DocumentFormat.OpenXml.Drawing.Stretch(

                                   new DocumentFormat.OpenXml.Drawing.FillRectangle()))));

  • Hi,

    Images in cells in PresentationML are designed for setting an image for the background, and not for displaying an image in a cell.  Here is how images work in cells in PresentationML:

    • You can set an image for a background in the cell, and have it resize with the cell.  This will cause the image to not retain its aspect ratio, or its native size.
    • You can set the image to tile.  This will then cause the image to retain its aspect ratio and size.  However, the image tiles relative to the entire table, not just to the cell.  You can set an X offset and Y offset for the tiling.  If done properly, you could, in theory, cause the image to tile (relative to the entire table) such that the image appears in the correct position in the cell.  However, if you resize any of the cells to the top or left of the cell that contains the image, the image will no longer be displayed properly in the cell.

    As you can see, neither one of the above behaviors is appropriate if you simply want to display an image in the cell.  As is indicated by the markup, you are really setting the image in the background, not as the contents of the cell.

    I wish I had a better answer for you, but I don't.  This is a current limitation of PresentationML.

    -Eric

  • Indeed, to further add to what Eric is saying, this is the exact same thing when filling a shape with a picture as it's background.

    The only way to get what you want is to know the dimension of either the height or the width of the cell and the size of the image. With that information you can use the l/r or t/b attributes of <a:fillRect/> of <a:stretch> under the <a:blipFill> portion of <a:tcPr> to set the relative size of the image. You could know this stuff in advance if you wanted to restrict the row height from getting larger based on the amount of text in other columns.

    So set the height of the row(s) and the width of the column(s) in advance and you can easily show a properly-dimensioned image as a background in the cell using the new DocumentFormat.OpenXml.Drawing.FillRectangle() routine you've started to creating already - the attributes "l, r, t, b" of <a:stretch>.<a:fillRect> uses the size of <a:srcRect> (which is the size of your cell) to both scale transform and translate transform your image within <a:srcRect>. Try it out manually in the PowerPoint client first and you'll set what I'm talking about.

  • Hi Todd Main,

    Can you please share me a sample code for the above?

    Thanks,

    Mano

  • Hi agbmano, I don't have a code sample (and I don't work with the SDK, so creating a sample may take too long). It would be a matter of trial on your side.

Page 1 of 1 (11 items)