1

これは、圧縮して JPG を保存するための私の MonoMac コードです。それは非常に簡単NSImageCompressionFactorです。見た目を設定するだけです。うまくいかないのは残念です。

public void SaveImage(NSImage MyNSImage,string Location, float Quality) 
{
    NSBitmapImageRep BRep=(NSBitmapImageRep)MyNSImage.Representations()[0]; 
    NSDictionary Dic= NSDictionary.FromObjectAndKey(new NSNumber(Quality),new NSString("NSImageCompressionFactor")); 
    NSData D=BRep.RepresentationUsingTypeProperties(NSBitmapImageFileType.Jpeg,Dic); 
    System.IO.Stream S=D.AsStream(); 
    SaveStream(Location,S); 
    S.Dispose(); 
    D.Dispose(); 
} 

//This save function works fine so ignore it.
void SaveStream(string FileName, Stream Source) 
{ 
    FileStream FS=File.OpenWrite(FileName); 
    int Read=0; 
    byte[] Buffer=new byte[1024]; 
    Source.Seek(0, SeekOrigin.Begin); 
    do{ 
        Read = Source.Read(Buffer, 0, 1024); 
        FS.Write(Buffer, 0, Read); 
    }while(Read>0); 
    FS.Close(); 
} 

常に 100% として保存されますが、何が間違っていますか? 賢い人が答えを知っていることを願っています。

4

3 に答える 3

0

これらすべてのプロパティ ディクショナリには、一般的な設計パターンがあります。それらのキーは、文字列ではなく文字列定数(その名前の変数) であり、Objective C ランタイムは、値ではなくアドレスによってそれらを照合します。

たとえば、あなたの場合、次のようにNSImageCompressionFactor宣言されています

NSString *NSImageCompressionFactor;

Objective C では、いくつかの定数文字列 (理論的には何でもかまいません) に初期化されます。基本的には、不透明な値へのポインタです。

Objective C でプロパティ ディクショナリを設定する場合NSImageCompressionFactor、新しい文字列インスタンス ( ) を作成する代わりに、変数の名前を使用します (つまり、単純に と記述します@"NSImageCompressionFactor")。

MonoMac では、これらの辞書キーの文字列プロパティを作成します。たとえば、MonoMac.Foundation.NSUrl.ContentAccessDateKeyを参照してください。

ただし、いくつかの場所で欠落しています (ビットマップ画像のプロパティはこれらの 1 つでした。monomac commit 115f1ebNSBitmapImageRepに追加しただけです)。今後、不足しているプロパティがさらに見つかった場合は、 にバグ レポートを提出してください。bugzilla.xamarin.com

古いバージョンの MonoMac を使用している場合の回避策もあります。ジェネレーターの入力ファイル ( monomac/src/appkit.cs ) では、これらは次のように宣言されています。

[Field ("NSImageCompressionMethod")]
NSString CompressionMethod { get; }

[Field ("NSImageCompressionFactor")]
NSString CompressionFactor { get; }

次に、ジェネレーターは以下を発行します。

[CompilerGenerated]
static readonly IntPtr AppKit_libraryHandle = Dlfcn.dlopen (Constants.AppKitLibrary, 0);
[CompilerGenerated]
static NSString _CompressionMethod;
public static NSString CompressionMethod {
    get {
        if (_CompressionMethod == null)
            _CompressionMethod = Dlfcn.GetStringConstant (AppKit_libraryHandle, "NSImageCompressionMethod");
        return _CompressionMethod;
    }
}
[CompilerGenerated]
static NSString _CompressionFactor;
public static NSString CompressionFactor {
    get {
        if (_CompressionFactor == null)
            _CompressionFactor = Dlfcn.GetStringConstant (AppKit_libraryHandle, "NSImageCompressionFactor");
        return _CompressionFactor;
    }
}

アプリのどこかで同じことを簡単に行うことができます。

アップデート

まず、Objective C の例を見てみましょう (完全なサンプルはこちら、画像はWikipediaからのものです)。

- (NSData *)saveImage:(NSImage *)image location:(NSString *)location quality:(float)quality {
    NSBitmapImageRep *imageRep = [[image representations] objectAtIndex:0];
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithFloat:quality], NSImageCompressionFactor, nil];

    NSData *data = [imageRep representationUsingType:NSJPEGFileType properties:dict];
    printf("DATA: %ld\n", [data length]);
    return data;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSString *resDir = [[path stringByAppendingPathComponent:@"Contents"] stringByAppendingPathComponent:@"Resources"];
    NSString *filePath = [resDir stringByAppendingPathComponent:@"Neptune.jpg"];

    NSImage *image = [[NSImage alloc] initWithContentsOfFile:filePath];

    [self saveImage:image location:@"output.jpg" quality:0.0];
    [self saveImage:image location:@"output.jpg" quality:0.25];
    [self saveImage:image location:@"output.jpg" quality:0.5];
    [self saveImage:image location:@"output.jpg" quality:1.0];
}

それでは、これを MonoMac アプリケーションに変えてみましょう (完全なサンプルはこちら)。

public override void FinishedLaunching (NSObject notification)
{
    mainWindowController = new MainWindowController ();
    mainWindowController.Window.MakeKeyAndOrderFront (this);

    var path = Path.Combine (NSBundle.MainBundle.BundlePath, "Contents", "Resources");
    var filePath = Path.Combine (path, "Neptune.jpg");

    var image = new NSImage (filePath);
    Console.WriteLine (image);

    SaveImage (image, "output.jpg", 0.0f);
    SaveImage (image, "output.jpg", 0.25f);
    SaveImage (image, "output.jpg", 0.5f);
    SaveImage (image, "output.jpg", 1.0f);
}

public void SaveImage (NSImage image, string location, float quality) 
{
    var brep = (NSBitmapImageRep)image.Representations ()[0];

    var dict = NSDictionary.FromObjectAndKey (NSNumber.FromFloat (quality), NSBitmapImageRep.CompressionFactor);

    var data = brep.RepresentationUsingTypeProperties (NSBitmapImageFileType.Jpeg, dict);
    Console.WriteLine (data.Length);
}

これは、Objective C のサンプルと同じサイズで出力されるため、実際に機能します。

于 2012-10-29T14:26:55.557 に答える
0

私は最終的にこれを上記のように機能させることをあきらめました。

この C# jpeg エンコーダーを見つけました。

http://www.codeproject.com/Articles/83225/A-Simple-JPEG-Encoder-in-C

コメントで指定されているように、1 行を修正する必要があります。

于 2012-11-28T16:18:58.133 に答える
0

OK、近づいていますが、まだ 100% 保存されています。他に何か提案はありますか?:

public void SaveImage(NSImage MyNSImage,string Location, float Quality) 
{

            NSBitmapImageRep BRep=(NSBitmapImageRep)MyNSImage.Representations()[0];
            NSDictionary Dic= NSDictionary.FromObjectAndKey(new NSNumber(Quality),NSImageCompressionFactor);
            NSData D=BRep.RepresentationUsingTypeProperties(NSBitmapImageFileType.Jpeg,Dic);
            System.IO.Stream S=D.AsStream();
            SaveStream(Location,S);
            S.Dispose();
            D.Dispose();

    }
    static readonly IntPtr AppKit_libraryHandle = MonoMac.ObjCRuntime.Dlfcn.dlopen (MonoMac.Constants.AppKitLibrary, 0);

    static NSString _NSImageCompressionFactor;
    public static NSString NSImageCompressionFactor {
        get {
            if (_NSImageCompressionFactor == null) {
                _NSImageCompressionFactor= MonoMac.ObjCRuntime.Dlfcn.GetStringConstant (AppKit_libraryHandle, "NSImageCompressionFactor");
            }
            return _NSImageCompressionFactor;
        }
    }
于 2012-11-14T19:53:19.237 に答える