locked
Reduce file size of a print quality image with programmatic text without losing print quality RRS feed

  • Question

  • User756353548 posted

    I need to load an image file, set some text on it, and save it as an image for printing using the code below.       

    private static void A4SizeDpi600() {
                    const int dotsPerInch = 600; // define the quality in DPI
                    const double widthInInch = 10; // width of the bitmap in INCH
                    const double heightInInch = 8; // height of the bitmap in INCH
        
                    using (Bitmap bitmap = new Bitmap(Image.FromFile(imageFilePath), (int)(widthInInch * dotsPerInch), (int)(heightInInch * dotsPerInch))) //10*600=6000, 8*600=4800
                    {
                        bitmap.SetResolution(dotsPerInch, dotsPerInch);
        
                        using (Graphics graphics = Graphics.FromImage(bitmap))
                        {
                          
                            graphics.DrawString("Some text here", new Font("Times New Roman", 0.3f, FontStyle.Regular, GraphicsUnit.Inch), Brushes.Black, 1400f, 2100f);
        ... //more text here
                        // Save the bitmap
                        bitmap.Save(imageBaseFilePath+ "CertDpi600.png");//file type can be any
                    }
                }


    The problem is that the resulting image is too big (10MB), the input file is only 600K, which is more than 10 times in size . I want to know if there are ways to reduce the file size without losing printing quality.

    The resulting image file type can be any type (pdf, png, bmp, jpeg), as long as it has good printing quality and small file size.

    I am open to the input file type too (either any image file type, or pdf), as long as it produces the same requirement above.

    Monday, July 24, 2017 6:39 PM

Answers

  • User991499041 posted

    Hi sxlin,

    I am looking for a solution that keeps the image dimension and resolution while reducing file size. By keeping both of them, the print quality remains the same.

    You could refer below code snippets to reduce images.

    private static Image ResizeImage(Image imgToResize, Size size)
        {
            int sourceWidth = imgToResize.Width;
            int sourceHeight = imgToResize.Height;
    
            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;
    
            nPercentW = ((float)size.Width / (float)sourceWidth);
            nPercentH = ((float)size.Height / (float)sourceHeight);
    
            if (nPercentH < nPercentW)
                nPercent = nPercentH;
            else
                nPercent = nPercentW;
    
            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);
    
            Bitmap b = new Bitmap(destWidth, destHeight);
            Graphics g = Graphics.FromImage((Image)b);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    
            g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
            g.Dispose();
    
            return (Image)b;
        }

    To use it like this

    int length = (int)stream.Length;
    byte[] tempImage = new byte[length];
    stream.Read(tempImage, 0, length);
    
    var image = new Bitmap(stream);
    var resizedImage = ResizeImage(image, new Size(300, 300));

    Regards,

    zxj

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, August 9, 2017 4:25 AM

All replies

  • User-718146471 posted

    There is one image format you might want to consider, vector images. Since Vectors are based on mathematic calculation, the end result image can be any size without sacrificing any quality. According to Taylor Dodds, he gives a great explanation of vector graphics vs other image formats.

    "If the logo is converted to vector art then size and dpi are not an issue. Vector art means that the shapes are not based on pixels or dots but lines that are build using anchor points and vector curves between them. These shapes can be scaled up or down to any size without the need for recalculating the pixel grid.

    Exporting these files for their intended use is where you will need to worry about dpi and size. It's pretty simple: screen resolution (for the vast majority) is 72 pixels per inch in a field of more than 1024x768 pixels. For print you will want 150 or 300dpi at 100% size, depending on the print process you are using and how detailed your images are.

    For video, working in 1080p (1080 vertical lines of 1920 pixels) is what you want for broadcast quality video. For a more in depth breakdown of ppi and dpi read this page from photographer Andrew Dacey." (https://www.quora.com/Whats-the-best-size-and-dpi-for-a-vector-format-logo-that-will-contain-a-variety-of-print-signs-and-other-graphics)

    Let me know if you would like to go down this road. 

    Monday, July 24, 2017 8:47 PM
  • User756353548 posted

    Hi bbcompent1,

    Using Vector images sounds great. I wonder if you could please provide code sample in C# to generate this.

    P.S. our existing file is pdf. However, the pdf is generated by a licensed tool which is not free. Thus, we are investigating if it is possible to generate it using a free tool.

    Monday, July 24, 2017 10:11 PM
  • User-707554951 posted

    Hi sxlin,

    For your problem, I think that you could consider to generate a thumbnail from images.

    The following c# method is used to generate thumbnail from image path

    Please refer to it:

    private void GenerateThumbnails(double scaleFactor, Stream sourcePath, string targetPath)
    {
    using (var image = Image.FromStream(sourcePath))
    {
    var newWidth = (int)(image.Width * scaleFactor);
    var newHeight = (int)(image.Height * scaleFactor);
    var thumbnailImg = new Bitmap(newWidth, newHeight);
    var thumbGraph = Graphics.FromImage(thumbnailImg);
    thumbGraph.CompositingQuality = CompositingQuality.HighQuality;
    thumbGraph.SmoothingMode = SmoothingMode.HighQuality;
    thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
    var imageRectangle = new Rectangle(0, 0, newWidth, newHeight);
    thumbGraph.DrawImage(image, imageRectangle);
    thumbnailImg.Save(targetPath, image.RawFormat);
    }
    }

    Related links;

    http://www.aspdotnet-suresh.com/2011/05/how-to-resize-size-image-without-losing.html

    http://www.c-sharpcorner.com/blogs/resizing-image-in-c-sharp-without-losing-quality1

    https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-create-thumbnail-images

    Best regards

    Cathy

    Tuesday, July 25, 2017 3:09 AM
  • User756353548 posted

    HI Cathy Zou,

    I need print quality, which need minimum of 300dpi. It is different from the screen resolution.

    http://www.urban75.org/photos/print.html

    Tuesday, July 25, 2017 9:01 AM
  • User756353548 posted

    Thanks. I will check it and mark as answer if it fits.

    Tuesday, July 25, 2017 11:25 PM
  • User-1865945774 posted

    Hello you can try using this

    using System.Drawing.Drawing2D;

    using System.Drawing.Imaging;

    System.Drawing.Image image = System.Drawing.Image.FromFile(imageFilePath);

    int newwidthimg = 1970;           

    float AspectRatio = (float)image.Size.Width / (float)image.Size.Height;

             int newHeight = Convert.ToInt32(newwidthimg / AspectRatio);

               Bitmap thumbnailBitmap = new Bitmap(newwidthimg, newHeight);

               Graphics thumbnailGraph = Graphics.FromImage(thumbnailBitmap);

               thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;

                thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;

                thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;

               var imageRectangle = new Rectangle(0, 0, newwidthimg, newHeight);

                thumbnailGraph.DrawImage(image, imageRectangle);

                thumbnailBitmap.Save(imageBaseFilePath,ImageFormat.Jpeg);

     thumbnailGraph.Dispose();

          thumbnailBitmap.Dispose();

                image.Dispose();  

    Wednesday, July 26, 2017 5:31 AM
  • User756353548 posted

    Hi,

    Thank you for your advice. I will check it, and let you know.

    Sunday, July 30, 2017 2:04 PM
  • User-707554951 posted

    Hi  sxlin

    Whether you solved his problem, if you have solved you problem , you could  share your solution.

    If not, please let me know and give lasted information about your problem.

    Best regards

    Cathy

    Wednesday, August 2, 2017 2:40 AM
  • User756353548 posted

    Hi Cathy,

    I am looking for a solution that keeps the image dimension and resolution while reducing file size. By keeping both of them, the print quality remains the same. Below is what I mean:

    //dimension remains the same 10*600=6000, 8*600=4800: (int)(widthInInch * dotsPerInch), (int)(heightInInch * dotsPerInch)
                   using (Bitmap bitmap = new Bitmap(Image.FromFile(imageFilePath), (int)(widthInInch * dotsPerInch), (int)(heightInInch * dotsPerInch))) 
                    {
                        bitmap.SetResolution(dotsPerInch, dotsPerInch);   //resolution: remains the same

    Any idea would be appreciated.

    Friday, August 4, 2017 9:16 AM
  • User991499041 posted

    Hi sxlin,

    I am looking for a solution that keeps the image dimension and resolution while reducing file size. By keeping both of them, the print quality remains the same.

    You could refer below code snippets to reduce images.

    private static Image ResizeImage(Image imgToResize, Size size)
        {
            int sourceWidth = imgToResize.Width;
            int sourceHeight = imgToResize.Height;
    
            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;
    
            nPercentW = ((float)size.Width / (float)sourceWidth);
            nPercentH = ((float)size.Height / (float)sourceHeight);
    
            if (nPercentH < nPercentW)
                nPercent = nPercentH;
            else
                nPercent = nPercentW;
    
            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);
    
            Bitmap b = new Bitmap(destWidth, destHeight);
            Graphics g = Graphics.FromImage((Image)b);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    
            g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
            g.Dispose();
    
            return (Image)b;
        }

    To use it like this

    int length = (int)stream.Length;
    byte[] tempImage = new byte[length];
    stream.Read(tempImage, 0, length);
    
    var image = new Bitmap(stream);
    var resizedImage = ResizeImage(image, new Size(300, 300));

    Regards,

    zxj

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, August 9, 2017 4:25 AM
  • User756353548 posted

    Hi Zxj,

    What resolution is used in the code? I can see the dimension is set to 300x300. The image need to be printed on an A4 size paper.

    I cannot see how the print quality will be the same.

    Wednesday, August 16, 2017 10:28 AM