4

ビットマップを取得し、その一部をコピーして8bpptiffとして保存する関数があります。結果イメージのファイル名は一意であり、ファイルは存在しません。プログラムには、ターゲットフォルダーへの書き込み権限があります。

void CropImage(Bitmap map) {
        Bitmap croped = new Bitmap(200, 50);

        using (Graphics g = Graphics.FromImage(croped)) {
            g.DrawImage(map, new Rectangle(0, 0, 200, 50), ...);
        }

        var encoderParams = new EncoderParameters(2);
        encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8L);
        encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone);

        croped.Save(filename, tiffEncoder, encoderParams);
        croped.Dispose();
    }

奇妙なことに、この機能は一部のコンピューター(Win 7)で正常に機能し、System.Runtime.InteropServices.ExternalExceptionをスローします。他のコンピューター(主にWin XP)のGDI例外で一般的なエラーが発生しました。

すべてのコンピューターには、.NET3.5SP1ランタイムがインストールされています。

croped.Save(filename, ImageFormat.Tiff);代わりに使用するcroped.Save(filename, tiffEncoder, encoderParams);と、すべてのコンピューターで機能しますが、Tiffを8bpp形式で保存する必要があります。

問題が発生する可能性のあるアイデアはありますか?

ありがとう、ルーカス

4

1 に答える 1

1

GDI は Windows オペレーティング システムの機能です。16 ビットの TIFF ファイルを扱っているときに同様の問題が発生し、別のライブラリに頼りました。c# からの LibTIFF の使用を参照してください。

MSDN ヘルプは、機能が利用可能であることを示唆していますが、ビットマップを新しいビットマップにコピーしようとしたり、ファイルまたはストリームに保存しようとすると、Windows は「一般的なエラー」例外をスローします。実際、同じ機能が Windows7 でもうまく機能します (これは TIFF を適切にサポートしているようです)。Windows 7 の新しい WIC 機能 を参照してください。

私が使用したもう 1 つの解決策は、8 ビットで安全でないコピーを作成することです。このようにして、PNGファイルを(パレットで)保存できました。私はこれをTIFFで試していません。

       // part of a function taking a proprietary TIFF tile structure as input and saving it into the desired bitmap format
      // tile.buf is a byterarray, containing 16-bit samples from TIFF.

        bmp = new Bitmap(_tile_width, _tile_height, PixelFormat.Format8bppIndexed);
        System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
        BitmapData bmpData =bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,bmp.PixelFormat);
        int bytes = bmpData.Stride * bmp.Height;

        dstBitsPalette = (byte *)bmpData.Scan0;

        offset=0;


        for (offset = 0; offset < _tile_size; offset += 2)
        {
             dstBitsPalette[offset >> 1] = tile.buf[offset + 1];
        }

        // setup grayscale palette
        ColorPalette palette = bmp.Palette;
        for (int i = 0; i < 256; i++)
        {
            Color c = Color.FromArgb(i, i, i);
            palette.Entries[i] = c;
        }
        bmp.Palette = palette;
        bmp.UnlockBits(bmpData);

        return bmp;

    }
于 2010-02-04T13:56:08.263 に答える