ConvertTo8bpp216 followed by Scale bug

Discussions about image processing and document imaging.
Post Reply
Username
Posts: 16
Joined: Wed Jul 18, 2012 12:11 am

ConvertTo8bpp216 followed by Scale bug

Post by Username » Sun Oct 07, 2012 3:22 am

Hi again,

I'm faced with weird GdPicture 9.2.4 behavior. In multithreading environment I want to convert some files to 8bb 216. Most of the files are converted normally but some of them are not - they are converted to different sizes compared to most of the resulting files. In my tests, source files (all they are the same file under different name) have these characteristic:

Source file:
Compression = CCITT T.4
DPI = 600
Bit depth = 1
Dimensions = 4968 x 7016
Size = 334 KB

After applying the same conversions to all my source files (100 in count - all are the same file under different name), I have the following 3 types of resulting files:
--------------------------------
Compression = LZW
DPI = 21
Bit depth = 8
Dimensions = 117 x 164
Size = 4,85 KB
--------------------------------
Comression = LZW
DPI = 42
Bit depth = 8
Dimensions = 348 x 491
Size = 8,48 KB
--------------------------------
Comression = LZW
DPI = 42
Bit depth = 8
Dimensions = 348 x 491
Size = 33,8 KB
--------------------------------

The last two files, even thou their characteristics look very similar (except file size) the image looks very different - the smaller file looks more like 1 bit compared to bigger one which looks more like 8 bit.

The resulting files are attached. Here is very simple code that produces this bug:

Code: Select all

var files = Directory.GetFiles(@"C:\PathWithAtLeast100Files","*.tif");
var po = new ParallelOptions { MaxDegreeOfParallelism = 6 };
Parallel.ForEach(files, po, (file, pls, idx) => {
    var gdp = new GdPictureImaging();
    var imageId = gdp.CreateGdPictureImageFromFile(file);
    gdp.ConvertTo8Bpp216(imageId);
    gdp.Scale(imageId, 7, System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic);
    gdp.SaveAsTIFF(imageId, file + ".converted.tif", TiffCompression.TiffCompressionLZW);
    gdp.ReleaseGdPictureImage(imageId);
    gdp.Dispose();
});
Note that I cannot see buggy results if I use ConvertTo8bppQ instead or other Convert* function.
Also if I remove either call to ConvertTo8Bpp216 or Scale methods, everything is OK. The problem persists only if these two calls are processed in this sequence. I have experience this bug even if i set MaxDegreeOfParallelism = 1 (which, hopefully, process files sequentially) - it produces one smallest file (4,85 KB) and all other were bigger one (33,8 KB). I think that every time I start the test with MaxDegreeOfParallelism = 1 (or simple for loop instead of Threads/Tasks), only the second file becomes 4,85 KB.

If this makes any sense - I'm using GdPicture 9.2.4 .NET 3.5 version with 32 bit "filters" file from 32 bit .NET 4 console application.
Attachments
Bug.zip
(41.72 KiB) Downloaded 369 times

User avatar
Loïc
Site Admin
Posts: 5881
Joined: Tue Oct 17, 2006 10:48 pm
Location: France
Contact:

Re: ConvertTo8bpp216 followed by Scale bug

Post by Loïc » Sun Oct 07, 2012 2:45 pm

Hello,

What is the status of each gdpicture method used? Maybe you are running through an out of memory state.

Kind regards,

Loïc

Username
Posts: 16
Joined: Wed Jul 18, 2012 12:11 am

Re: ConvertTo8bpp216 followed by Scale bug

Post by Username » Sun Oct 07, 2012 6:40 pm

Hi,

Please ignore this text "I think that every time I start the test with MaxDegreeOfParallelism = 1 (or simple for loop instead of Threads/Tasks), only the second file becomes 4,85 KB." - It is normal because one of the files was different than all others.
Only the problem with "sometimes some of the resulting files have different size even thou all source files are the same".
The Status from each GdPicture call is OK. This is my real production code that suffers this issue - if status is not OK then it throws exception - I have placed breakpoint to it but it never hits.

Code: Select all

        public ScaleImageResponse ScaleImage(ScaleImageRequest request) {
            ScaleImageResponse response = new ScaleImageResponse();

            GdPictureImaging img = GetNewGdPictureImaging();
            int imageId = img.CreateGdPictureImageFromFile(request.SourceFileName);
            int clonedImageId = 0;
            int[] imagesToRelease = new[] { imageId };

            Func<Func<GdPictureStatus>, GdPictureStatus> ExecStatusLocal = statFuncLocal => {
                GdPictureStatus statLocal = ExecStatus(statFuncLocal, img, null, imagesToRelease);
                return statLocal;
            };

            ExecStatusLocal(img.GetStat);
            if (request.Percent != 100) {
                if (request.ConversionParameters != null) {
                    ExecStatusLocal(() => ChangeImageColorFormat(img, imageId, request.ConversionParameters.PixelFormat));
                }
                ExecStatusLocal(() => img.Scale(imageId, request.Percent, InterpolationMode.HighQualityBicubic));
            }

            if (!string.IsNullOrEmpty(request.DestinationFileName)) {
                TiffCompression compression;
                if (request.ConversionParameters != null) {
                    compression = _mapper.ToTiffCompression(request.ConversionParameters.Compression);
                } else {
                    compression = TiffCompression.TiffCompressionLZW;
                }
                ExecStatusLocal(() => img.SaveAsTIFF(imageId, request.DestinationFileName, compression));
            }
            ExecStatusLocal(() => img.ReleaseGdPictureImage(imageId));
            img.Dispose();
            return response;
        }

        private GdPictureStatus ExecStatus(Func<GdPictureStatus> func, GdPictureImaging gdpImg, GdPicturePDF gdpPdf, IEnumerable<int> imageIdsToRelease) {
            GdPictureStatus result = func();
            CheckStatus(result, func, gdpImg, gdpPdf, imageIdsToRelease);
            return result;
        }

        private void CheckStatus(GdPictureStatus status, Delegate func, GdPictureImaging gdpImg, GdPicturePDF gdpPdf, IEnumerable<int> imageIdsToRelease) {
            if (status != GdPictureStatus.OK) {
                // Cleanup
                if (gdpImg != null) {
                    if (imageIdsToRelease != null) {
                        foreach (var item in imageIdsToRelease) {
                            if (item != 0) {
                                gdpImg.ReleaseGdPictureImage(item);
                            }
                        }
                    }
                    gdpImg.Dispose();
                }

                if (gdpPdf != null) {
                    gdpPdf.CloseDocument();
                    gdpPdf.Dispose();
                }
                throw new Exception(string.Format("{0} : Method = {1} ; Target = {2}", status, func.Method, func.Target));
            }
        }

        private GdPictureStatus ChangeImageColorFormat(GdPictureImaging gdpImg, int imageId, PixelFormat newColorFormat) {
            if (newColorFormat == PixelFormat.Undefined) {
                return GdPictureStatus.OK;
            }
            int[] imagesToRelease = new[] { imageId };
            Func<Func<GdPictureStatus>, GdPictureStatus> ExecStatusLocal = statFuncLocal => {
                GdPictureStatus statResultLocal = ExecStatus(statFuncLocal, gdpImg, null, imagesToRelease);
                return statResultLocal;
            };
            GdPictureStatus gdStatus = GdPictureStatus.GenericError;
            PixelFormat currentPixelFormat = gdpImg.GetPixelFormat(imageId);
            ExecStatusLocal(gdpImg.GetStat);
            if (currentPixelFormat == newColorFormat) {
                return GdPictureStatus.OK;
            }
            if (newColorFormat == PixelFormat.Format8bppIndexed) {
                ExecStatusLocal(() => gdpImg.ConvertTo8Bpp216(imageId));
            } else if (newColorFormat == PixelFormat.Format1bppIndexed) {
                ExecStatusLocal(() => gdpImg.ConvertTo1BppAT(imageId));
            } else if (newColorFormat == PixelFormat.Format24bppRgb) {
                ExecStatusLocal(() => gdpImg.ConvertTo24BppRGB(imageId));
            }
            gdStatus = GdPictureStatus.OK;
            return gdStatus;
        }

User avatar
Loïc
Site Admin
Posts: 5881
Joined: Tue Oct 17, 2006 10:48 pm
Location: France
Contact:

Re: ConvertTo8bpp216 followed by Scale bug

Post by Loïc » Sun Oct 07, 2012 6:56 pm

Hello,

OK. I am totally lost with your explanations. And we really need to reproduce the problem to advice.

Please reproduce the issue in a standalone application that you can send to our team through our helpdesk system located here: https://www.gdpicture.com/support/getting-support-from-our-team

Kind regards,

Loïc

Username
Posts: 16
Joined: Wed Jul 18, 2012 12:11 am

Re: ConvertTo8bpp216 followed by Scale bug

Post by Username » Sun Oct 07, 2012 7:39 pm

This is a sample code - .NET 4.0 console application with reference to GdPicture 9.2.4 from .NET 3.5 folder in your installation. Sample TIF source file is attached - every similar file should work. I have changed the code to use single source file in order to be very easy to setup your environment. Just create a directory where resulting files should be created.

Code: Select all

namespace GdPictureIssue {
    class Program {
        static void Main(string[] args) {
            RegisterGdPictureLicenses();
            int numberOfFiles = 100;
            List<ScaleImageRequest> requestList = new List<ScaleImageRequest>();
            for (int i = 0; i < numberOfFiles; i++) {
                ScaleImageRequest req = new ScaleImageRequest();
                string idxString = (i + 1).ToString();
                req.SourceFileName = @"C:\GdPictureIssue.tif";
                req.Percent = 7;
                req.DestinationFileName = @"C:\GdPictureIssueDestination\DestinationFile-" + idxString + ".tif";
                requestList.Add(req);
            }
            ParallelOptions po = new ParallelOptions();
            po.MaxDegreeOfParallelism = 6;

            Action<Func<GdPictureStatus>> checkStatus = statusFunc => {
                GdPictureStatus status = statusFunc();
                if (status != GdPictureStatus.OK) {
                    Console.WriteLine(status);
                }
            };

            Parallel.ForEach(requestList, po, (x, pls, idx) => {
                GdPictureImaging gdp = new GdPictureImaging();
                int imageId = gdp.CreateGdPictureImageFromFile(x.SourceFileName);
                checkStatus(gdp.GetStat);
                checkStatus(() => gdp.ConvertTo8Bpp216(imageId));
                checkStatus(() => gdp.Scale(imageId, x.Percent, System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic));
                checkStatus(() => gdp.SaveAsTIFF(imageId, x.DestinationFileName, TiffCompression.TiffCompressionLZW));
                checkStatus(() => gdp.ReleaseGdPictureImage(imageId));
                gdp.Dispose();
            });

            Console.WriteLine("Finished");
            Console.ReadLine();
        }

        private static void RegisterGdPictureLicenses() {
            string[] licenseKeys = new[] { "My GdPicture v8 license key", 
                                           "My GdPicture v8 to v9 upgrade license key", 
                                           "My GdPicture v9 PDF plug-in license key" };
            LicenseManager lm = new LicenseManager();
            foreach (var key in licenseKeys) {
                lm.RegisterKEY(key);
            }
        }
    }

    public class ScaleImageRequest {
        public string SourceFileName { get; set; }
        public float Percent { get; set; }
        public string DestinationFileName { get; set; }
    }
}
Now run the code and look at the destination folder - all files should be the same because source file is the same and all the transformations are the same for each output file. But you can see that there are 2 different type of files - most of them are 44 KB (correct one) and few of them are 11 KB (wrong one). From my last test, 15 of total 100 files were wrong (11 KB only compared to the rest of the files which are 44 KB). Also look at console window - if one or more of returned GdPictureStatus is not OK, it will be written to the console. No such messages appear but still output is wrong.
Attachments
GdPictureIssue.tif
Sample TIFF - G4, LZW, 600 dpi, 5100 x 6600

User avatar
Loïc
Site Admin
Posts: 5881
Joined: Tue Oct 17, 2006 10:48 pm
Location: France
Contact:

Re: ConvertTo8bpp216 followed by Scale bug

Post by Loïc » Mon Oct 08, 2012 10:57 am

Sorry but I am not able to use your code. Please provide a standalone application. We can't work in another way.

Kind regards,

Loïc

Username
Posts: 16
Joined: Wed Jul 18, 2012 12:11 am

Re: ConvertTo8bpp216 followed by Scale bug

Post by Username » Mon Oct 08, 2012 5:21 pm

Sample application is attached.

Reference GdPicture v 9.2.4 in "Framework 3.5" folder where GdPicture is installed (C:\Program Files (x86)\GdPicture.NET 9\Redist\Framework 3.5).

Copy sample file from previous post to:
C:\GdPictureIssue.tif

For resulting files, create the following directory:
C:\GdPictureIssueDestination\

Change license keys in RegisterGdPictureLicenses() method.
Attachments
ConsoleApplication1.zip
(29.35 KiB) Downloaded 373 times

User avatar
Loïc
Site Admin
Posts: 5881
Joined: Tue Oct 17, 2006 10:48 pm
Location: France
Contact:

Re: ConvertTo8bpp216 followed by Scale bug

Post by Loïc » Mon Oct 08, 2012 5:47 pm

Hello,

The project is empty. Am I missing something ?

Username
Posts: 16
Joined: Wed Jul 18, 2012 12:11 am

Re: ConvertTo8bpp216 followed by Scale bug

Post by Username » Mon Oct 08, 2012 6:04 pm

Sorry. forgot to save the project before compressing. New one is attached.
Attachments
ConsoleApplication3.zip
(644.5 KiB) Downloaded 355 times

User avatar
Loïc
Site Admin
Posts: 5881
Joined: Tue Oct 17, 2006 10:48 pm
Location: France
Contact:

Re: ConvertTo8bpp216 followed by Scale bug

Post by Loïc » Tue Oct 09, 2012 6:01 pm

I was able to process 100000 files without any issue, with our current beta release that includes optimization on the ConvertTo8Bpp216() method.
Our next release will be published next week but if you need a beta you can contact us through https://www.gdpicture.com/support/getting-support-from-our-team

Kind regards,

Loïc

Username
Posts: 16
Joined: Wed Jul 18, 2012 12:11 am

Re: ConvertTo8bpp216 followed by Scale bug

Post by Username » Tue Oct 09, 2012 6:32 pm

I will request beta version from support site.

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests