Hi Marti,
Also forgot to mention, that i use c#.
Try to simplify the codes here.
This is working solution if use without multi-threading:
***
[DllImport("lcms2.dll")]
public static extern IntPtr cmsCreateTransform(IntPtr hInputProfile,
UInt32 InputFormat, IntPtr hOutputProfile, UInt32 OutputFormat, UInt32 Intent,
UInt32 dwFlags);
[DllImport("lcms2.dll")]
public static extern void cmsDoTransformLineStride(IntPtr hTransform,
byte[] InputBuffer, byte[] OutputBuffer, UInt32 PixelsPerLine, UInt32 LineCount,
UInt32
BytesPerLineIn, UInt32 BytesPerLineOut, UInt32 BytesPerPlaneIn, UInt32
BytesPerPlaneOut);
public static class Profiles
{
private static IntPtr __hMonitor = IntPtr.Zero;
public static IntPtr hMonitor { get { return __hMonitor; } set {
__hMonitor = value; } }
// etc.
}
[HandleProcessCorruptedStateExceptions]
public BitmapSource LoadSingleFile(string filename)
{
var ms = LoadImageFileToMemoryStream(filename);
BitmapFrame bf = BitmapFrame.Create(ms,
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
IntPtr hInput, hMonitor;
byte[] inputProfile =
StreamToByteArray(bf.ColorContexts[0].OpenProfileStream()); // Check it
before, if not available, create one on-the-fly in the actual format
hInput = cmsOpenProfileFromMem(inputProfile,
(uint)inputProfile.Length);
// Monitor Profile: opened earlier and located in Profiles.hMonitor;
IntPtr hTransform = IntPtr.Zero;
int BytesPerPixelIn = 0;
int StrideIn = 0;
int SizeIn = 0;
byte[] PixelsIn;
UInt32 TypeIn = 0;
int BytesPerPixelOut = 0;
int StrideOut = 0;
int SizeOut = 0;
byte[] PixelsOut;
UInt32 TypeOut = 0;
// CHECK INPUT FORMATS
if (bf.Format == PixelFormats.Bgr24)
{
BytesPerPixelIn = BytesPerPixelOut = 3;
StrideIn = StrideOut = ((bf.PixelWidth * BytesPerPixelIn) +
(bf.PixelWidth % 4));
SizeIn = SizeOut = StrideIn * bf.PixelHeight;
PixelsIn = new byte[SizeIn];
PixelsOut = new byte[SizeOut];
TypeIn = TypeOut = LittleCMS.LCMS.TYPE_BGR_8;
bf.CopyPixels(PixelsIn, StrideIn, 0);
}
else if (bf.Format == PixelFormats.Cmyk32)
{
BytesPerPixelIn = bf.Format.BitsPerPixel / 8; // In this
case: 4
BytesPerPixelOut = 3;
StrideIn = ((bf.PixelWidth * BytesPerPixelIn) + (bf.PixelWidth
% 4));
StrideOut = ((bf.PixelWidth * BytesPerPixelOut) +
(bf.PixelWidth % 4));
SizeIn = StrideIn * bf.PixelHeight;
SizeOut = StrideOut * bf.PixelHeight;
PixelsIn = new byte[SizeIn];
PixelsOut = new byte[SizeOut];
TypeIn = LittleCMS.LCMS.TYPE_CMYK_8;
TypeOut = LittleCMS.LCMS.TYPE_BGR_8;
bf.CopyPixels(PixelsIn, StrideIn, 0);
}
// etc., etc., etc....
else
{
// Using FormatConvertedBitmap class and do the first step
var fcb = new FormatConvertedBitmap(bmp,
System.Windows.Media.PixelFormats.Bgr24, null, 0));
}
// Create the transform
try
{
hTransform = cmsCreateTransform(hInput, TypeIn, hMonitor,
TypeOut, iFlags, dwFlags);
}
catch (AccessViolationException)
{
return null;
}
catch (Exception e)
{
return null;
}
// Do the transform: VERSION 1. simple transform
try
{
cmsDoTransformLineStride(hTransform, PixelsIn, PixelsOut,
(uint)bf.PixelWidth, (uint)partHeight, (uint)StrideIn, (uint)StrideOut, 0, 0);
}
catch (AccessViolationException)
{
return null;
}
catch (Exception e)
{
return null;
}
// Do the transform: VERSION 2: This is also a single thread
version, what i can change to use multi-threaded, and works fine.
try
{
int cores = Environment.ProcessorCount; ;
int partHeight = bf.PixelHeight / cores;
int lastPlaceIn = 0, lastPlaceOut = 0;
for (int i = 0; i < cores; i++)
{
int tSizeIn = 0;
int tSizeOut = 0;
if (i == (cores - 1))
{
partHeight = (bf.PixelHeight - (cores - 1) *
partHeight);
}
tSizeIn = partHeight * StrideIn;
tSizeOut = partHeight * StrideOut;
byte[] tPixelsIn = new byte[tSizeIn];
byte[] tPixelsOut = new byte[tSizeOut];
Array.Copy(PixelsIn, lastPlaceIn, tPixelsIn, 0, tSizeIn);
lastPlaceIn = ((i + 1) * partHeight * StrideIn);
cmsDoTransformLineStride(hTransform, tPixelsIn, tPixelsOut,
(uint)bf.PixelWidth, (uint)partHeight, (uint)StrideIn, (uint)StrideOut, 0, 0);
if (i == (cores - 1))
Array.Copy(tPixelsOut, 0, PixelsOut, lastPlaceOut,
tSizeOut);
else
{
Array.Copy(tPixelsOut, 0, PixelsOut, lastPlaceOut,
tSizeOut);
lastPlaceOut = ((i + 1) * partHeight * StrideOut);
}
}
// catch exceptions....
BitmapSource ccb = BitmapSource.Create(bf.PixelWidth,
bf.PixelHeight, bf.DpiX, bf.DpiY, PixelFormats.Bgr24, null, PixelsOut,
StrideOut);
cmsDeleteTransform(hTransform);
cmsCloseProfile(hInput);
// cmsCloseProfile(hMonitor); - Not Close Monitor Profile
because i would like to use it for the next file(s), too.
return ccb;
}
***
So, when i open only one image and call the LoadSingleFile method, everything
works nice.
When i load multiple files and use the LoadSingleFile method in a for loop,
everything works nice.
When i load multiple files and put the LoadSingleFiles method in a for loop and
each of them starts in different thread, everything works nice till the files
has the same sRGB profiles and 24bit depth.
If i put e.g. a CMYK image (anything else, but different then the previously
used format), that is the point where the problem begins....
The error is about the AccessViolationException during the cmsCreateTransform
or rarely in the DoTransform / cmsDeleteTransform / cmsDeleteProfile.
"Attempted to read or write protected memory. This is often an indication that
other memory is corrupt."
And best error is when the vshost.exe (during debugging) crashed - without any
information about the problem.
If i need to use cmsContexts (and the errorhandling) i also have no clues about
how to declare them in C-Sharp.
Let me know if you need more infos.
Thanks a lot,
*Tamas*
-- Eredeti üzenet --
Feladó: Marti Maria @ LittleCMS <marti.ma...@littlecms.com>Címzett:
<liti1...@vipmail.hu>, <lcms-user@lists.sourceforge.net>Elküldve:
2017. január 8. 19:48Tárgy : Re: [Lcms-user] Multi-Threading in VS
Hi Tamas,
Could you please detail which errors you get? I'm using multi threading without
problems, so maybe something is wrong, perhaps In the documentation.
Best regards,
Marti On 8 Jan 2017, at 18:47, liti1...@vipmail.hu wrote: Dear All,
I am using lcms2.dll and their standard methods and all of them works fine in a
single-thread environment. (I was able to use cmsDoTransformLineStride
multi-threaded when this is the only function which is using multiple threads.
My question is about e.g. if i would like to use as a batch process across
multiple/different image files and the whole image process put into different
threads per files .)
When i tried to put them in a multi-threaded environment, always get errors. I
try to understand the cmsContexts and start to experiment with them, but it
seems something i missed.
Can anybody provide me a simple sample code of how should i use these functions
(with dll declaration, too)?
Also, i would be happy if someone provide me a sample about the error handling
function.
In case both questions, I'm using WPF in VS 2015.
Thanks,
*Tamas*
Check out the vibrant tech community on one of the world's most
e ngaging tech sites, SlashDot.org! http://sdm.link/slashdot
Lcms-user mailing list
Lcms-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lcms-user
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Lcms-user mailing list
Lcms-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lcms-user