0
votes

Currently I´m still on Nav2009R2 classic using a C# library with COM classes through Interop. My some 20000 pictures are Jpegs and not stored within the DBs blobs, but on a simple network share. To convert to bmp and scale those pictures, I wrote a litte C# function a couple of years ago, which still works fine. It reads the jpeg from a file, converts and scales it, and writes that bmp to a stream through which Nav can access it. Very fast, very stable and easy to use within Nav:

  // just bind "TempRec.BlobField" to the picture control, and that´s it within Nav
  IF ISCLEAR(LocAutImaging) THEN CREATE(LocAutImaging, FALSE, TRUE);
   TempRec.BlobField.CREATEINSTREAM(LocStreamPreviewPic);
   LocAutImaging.ConvertFileToBmpStream(LocStreamPreviewPic, '\\..\..\Picture.jpg', 300, 300);
  CLEAR(LocAutImaging);

Using streams with Nav and C# was a bit tricky, but it works:

    public void ConvertFileToBmpStream(object ObjPictureStream, string StrSourceFile, int NewHeigth, int NewWidth)
    {
        Bitmap MyBitMap = null;
        IStream StmPicStream = ObjPictureStream as IStream;
        MemoryStream ms = new MemoryStream();
        IntPtr rwBytes = Marshal.AllocHGlobal(4);

        Image img = Image.FromFile(StrSourceFile);
        Size MySize = new Size(NewWidth, NewHeigth);
        if (NewHeigth == 0 & NewWidth == 0){ MyBitMap = new Bitmap(img); } else { MyBitMap = new Bitmap(img, MySize); }

        MyBitMap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
        int StreamLength = Convert.ToInt32(ms.Length);

        byte[] buffer = new byte[StreamLength];
        buffer = ms.ToArray();

        StmPicStream.Write(buffer, StreamLength, rwBytes);
        Marshal.FreeHGlobal(rwBytes);
        ms.Dispose();
        img.Dispose();
        MyBitMap.Dispose();
    }

While everything is fine with that, we are now working on the Nav 2016 Update. With the RTC, COM Controls can still be used on the client side; BUT .. NO CHANCE, if you are using streams! And on the other hand, you cannot not use a Interop COM function to be run on the Nav Server.

That means, that I´ll have to implement this code as a method within a pure .Net class, without the Interop-Interface. Unfortunately I have no idea, how to pass a stream from Nav to the .Net method, so it can be read and written as in the above sample. Is it still the best way, to use that general "object" type and to cast this to an IStream?

Thanks in advance

Pidi

1
I would like to convert images to bitmaps so I store them in a blob file. Could you provide more description on how you accomplished thatGilbert

1 Answers

1
votes

here is a code instead which is using DotNet to resize the image

ResizePhoto(Filename : Text;NewFilePath : Text;MaxHeight : Integer)
IF Filename = '' THEN
  IF GUIALLOWED THEN ERROR(NoFilename) ELSE EXIT;

IF NewFilePath = '' THEN BEGIN
  DirectoryInfo := DirectoryInfo.DirectoryInfo(Path.GetDirectoryName(NewFilePath));
  IF NOT DirectoryInfo.Exists THEN
    IF GUIALLOWED THEN ERROR(STRSUBSTNO(NewDirectoryDoesntExists,DirectoryInfo.Name)) ELSE EXIT;
END;

IF MaxHeight = 0 THEN
  IF GUIALLOWED THEN ERROR(NoNewSize) ELSE EXIT;

AuctionSetup.GET;
IF GUIALLOWED THEN Setup.TESTFIELD("Photo Pool Path") 
ELSE IF Setup."Photo Pool Path" = '' THEN ERROR(NoPhotoPoolPath);

Filepath := Path.Combine(Setup."Photo Pool Path",Filename);
IF NewFilePath = '' THEN NewFilePath := Filepath;

Image := Image.FromFile(Filepath);

Pct := MaxHeight / Image.Height;
NewWidth := ROUND(Image.Width * Pct,1);
NewHeight := ROUND(Image.Height * Pct,1);

Bitmap := Bitmap.Bitmap(NewWidth,NewHeight);
Graphics := Graphics.FromImage(Bitmap);
InterpolationMode := InterpolationMode.HighQualityBicubic;
Graphics.InterpolationMode := InterpolationMode;
SmoothingMode := SmoothingMode.HighQuality;
Graphics.SmoothingMode := SmoothingMode;
PixelOffsetMode := PixelOffsetMode.HighQuality;
Graphics.PixelOffsetMode := PixelOffsetMode;
Graphics.DrawImage(Image,0,0,NewWidth,NewHeight);
Graphics.Dispose;
Image.Dispose;

ImageFormat := ImageFormat.Jpeg;
Bitmap.Save(NewFilePath,ImageFormat);

Variables:

Name            DataType    Subtype Length
Setup           Record      Setup   
Filepath        Text            
Path            DotNet      System.IO.Path.'mscorlib'   
DirectoryInfo       DotNet      System.IO.DirectoryInfo.'mscorlib'  
Image           DotNet      System.Drawing.Image.'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'    
Bitmap          DotNet      System.Drawing.Bitmap.'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'   
Graphics        DotNet      System.Drawing.Graphics.'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 
InterpolationMode   DotNet      System.Drawing.Drawing2D.InterpolationMode.'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'  
SmoothingMode       DotNet      System.Drawing.Drawing2D.SmoothingMode.'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'  
PixelOffsetMode     DotNet      System.Drawing.Drawing2D.PixelOffsetMode.'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'    
ImageFormat     DotNet      System.Drawing.Imaging.ImageFormat.'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'  
Pct         Decimal     
HeightPct       Decimal     
WidthPct        Decimal     
NewWidth        Integer     
NewHeight       Integer     
NewWidthDec     Decimal     
NewHeightDec        Decimal     
DecimalZero     Decimal     

Usage:

ConvertFileNameDotNet(FileName : Text;Resolution : Integer;VAR Image : TEMPORARY Record TempBitmapBlob)
IF Resolution = 0 THEN Resolution := 300;
Setup.GET;
Setup.TESTFIELD("Photo Pool Path");

GUID := FORMAT(CREATEGUID);
ConvertedServerTempFilePath := 'C:\TEMP\' + GUID + '_CONVERTED.JPG';
IF EXISTS(ConvertedServerTempFilePath) THEN IF ERASE(ConvertedServerTempFilePath) THEN;
IF NOT EXISTS(Setup."Photo Pool Path" + FileName) THEN EXIT;

ResizePhoto(FileName,ConvertedServerTempFilePath,Resolution);

IF EXISTS(ConvertedServerTempFilePath) THEN BEGIN
  FileManagement.BLOBImportFromServerFile(TempBlob,ConvertedServerTempFilePath);
  Image.Blob := TempBlob.Blob;
  IF EXISTS(ConvertedServerTempFilePath) THEN IF ERASE(ConvertedServerTempFilePath) THEN;
END;

I can send you object in txt if you want.

Cheers!