You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// add the "Presentation Core" assembly to access thisusingSystem.Windows.Media;usingSystem.Windows.Media.Imaging;/// <summary>/// This function takes a TIFF frame of any bit depth and returns a proper 8-bit bitmap/// </summary>privateBitmapLoadImageTiff(stringpath,intframeNumber=0){//bmpPreview = new Bitmap(path);// open a file stream and keep it open until we're done reading the fileStreamstream=newFileStream(path,FileMode.Open,FileAccess.Read,FileShare.Read);// carefully open the file to see if it will decodeTiffBitmapDecoderdecoder;try{decoder=newTiffBitmapDecoder(stream,BitmapCreateOptions.PreservePixelFormat,BitmapCacheOption.Default);}catch{Console.WriteLine("TiffBitmapDecoder crashed");stream.Dispose();returnnull;}// access information about the imageintimageFrames=decoder.Frames.Count;BitmapSourcebitmapSource=decoder.Frames[frameNumber];intsourceImageDepth=bitmapSource.Format.BitsPerPixel;intbytesPerPixel=sourceImageDepth/8;SizeimageSize=newSize(bitmapSource.PixelWidth,bitmapSource.PixelHeight);intpixelCount=imageSize.Width*imageSize.Height;// fill a byte array with source data bytes from the fileintimageByteCount=pixelCount*bytesPerPixel;byte[]bytesSource=newbyte[imageByteCount];bitmapSource.CopyPixels(bytesSource,imageSize.Width*bytesPerPixel,0);// we can now close the original filestream.Dispose();// now convert the byte array to an int array (with 1 int per pixel)int[]valuesSource=newint[pixelCount];for(inti=0;i<valuesSource.Length;i++){// this loop is great because it works on any number of bytes per pixelintbytePosition=i*bytesPerPixel;for(intbyteNumber=0;byteNumber<bytesPerPixel;byteNumber++){valuesSource[i]+=bytesSource[bytePosition+byteNumber]<<(byteNumber*8);}}// determine the range of intensity dataintpixelValueMax=valuesSource.Max();intpixelValueMin=valuesSource.Min();// predict what bit depth we have based upon pixelValueMaxintdataDepth=1;while(Math.Pow(2,dataDepth)<pixelValueMax)dataDepth++;// determine if we will use the original bit depth or our guessed bit depthbooluse_detected_camera_depth=true;// should this be an argument?if(!use_detected_camera_depth)dataDepth=sourceImageDepth;// create and fill a pixel array for the 8-bit final imagebyte[]pixelsOutput=newbyte[pixelCount];for(inti=0;i<pixelsOutput.Length;i++){// start by loading the pixel value of the sourceintpixelValue=valuesSource[i];// upshift it to the nearest byte (if using a nonstandard depth)pixelValue=pixelValue<<(sourceImageDepth-dataDepth);// downshift it as needed to ensure the MSB is in the lowest 8 bytespixelValue=pixelValue>>(sourceImageDepth-8);// conversion to 8-bit should be now nondestructivepixelsOutput[i]=(byte)(pixelValue);}// input bytes are padded such that stide is a multiple of 4 bytes, so trim it offintstrideByteMultiple=4;intstrideOverhang=imageSize.Width%strideByteMultiple;Log($"Width-stride overhang: {strideOverhang} bytes");if(strideOverhang>0){intstrideBytesNeededPerRow=strideByteMultiple-(strideOverhang);Log($"Trimming {strideBytesNeededPerRow} extra bytes from the end of each row");byte[]pixelsOutputOriginal=newbyte[pixelCount];Array.Copy(pixelsOutput,pixelsOutputOriginal,pixelCount);pixelsOutput=newbyte[pixelCount+strideBytesNeededPerRow*imageSize.Height];intnewStrideWidth=imageSize.Width+strideBytesNeededPerRow;for(introw=0;row<imageSize.Height;row++)for(intcol=0;col<imageSize.Width;col++)pixelsOutput[row*newStrideWidth+col]=pixelsOutputOriginal[row*imageSize.Width+col];}// create the output bitmap (8-bit indexed color)varformat=System.Drawing.Imaging.PixelFormat.Format8bppIndexed;Bitmapbmp=newBitmap(imageSize.Width,imageSize.Height,format);// Create a grayscale palette, although other colors and LUTs could go hereColorPalettepal=bmp.Palette;for(inti=0;i<256;i++)pal.Entries[i]=System.Drawing.Color.FromArgb(255,i,i,i);bmp.Palette=pal;// copy the new pixel data into the data of our output bitmapvarrect=newRectangle(0,0,imageSize.Width,imageSize.Height);BitmapDatabmpData=bmp.LockBits(rect,ImageLockMode.ReadOnly,format);Marshal.Copy(pixelsOutput,0,bmpData.Scan0,pixelsOutput.Length);bmp.UnlockBits(bmpData);returnbmp;}