views:

459

answers:

1

I need to rotate an image that is passed to a function as an array of BitmapFrames. the finished product needs to be saved as a BitmapFrame as well so I can send it to my Export-Image function. Help?

[Cmdlet(VerbsData.ConvertTo, "Rotate")]
public class RotateCmdlet : PSCmdlet
{
    private BitmapFrame[] bFrame, outFrame;
    private BitmapSource src;
    private double pixelsize;
    private int degrees;
    private byte[] pixels, outPixels;

    [Parameter(ValueFromPipeline = true,
        ValueFromPipelineByPropertyName = true), ValidateNotNullOrEmpty]
    public BitmapFrame[] Bitmap
    {
        get
        {
            return bFrame;
        }
        set
        {
            bFrame = value;
        }
    }

    [Parameter(Position = 0), ValidateNotNullOrEmpty]
    public int Degrees
    {
        get
        {
            return degrees;
        }
        set
        {
            degrees = value;
        }
    }

    protected override void ProcessRecord()
    {
        base.ProcessRecord();
        Console.Write("Rotating the image {0} degrees...\n\n", degrees);
        outFrame = new BitmapFrame[bFrame.Length];
        for (int c = 0; c < bFrame.Length; c++)
        {
            Image image;

            pixelsize = bFrame[c].PixelWidth * bFrame[c].PixelHeight;
            pixels = new byte[(int)pixelsize];
            outPixels = new byte[(int)pixelsize];
            bFrame[c].CopyPixels(pixels, (int)(bFrame[c].Width * (bFrame[c].Format.BitsPerPixel / 8.0)), 0);

            Stream strm = new MemoryStream(pixels);
            image = Image.FromStream(strm);

            var newBitmap = new Bitmap((int)bFrame[c].PixelWidth, (int)bFrame[c].PixelHeight);
            var graphics = Graphics.FromImage(newBitmap);
            graphics.TranslateTransform((float)bFrame[c].PixelWidth / 2, (float)bFrame[c].PixelHeight / 2);
            graphics.RotateTransform(degrees);
            graphics.TranslateTransform(-(float)bFrame[c].PixelWidth / 2, -(float)bFrame[c].PixelHeight / 2);
            graphics.DrawImage(image, new System.Drawing.Point(0, 0));

            for (int i = 0; i < pixelsize; i++)
            {
                outPixels[i] = pixels[i];
            }

            src = BitmapSource.Create(bFrame[c].PixelWidth, bFrame[c].PixelHeight, bFrame[c].DpiX, bFrame[c].DpiY,
                bFrame[c].Format, bFrame[c].Palette, outPixels, (int)(bFrame[c].Width * (bFrame[c].Format.BitsPerPixel / 8)));
            outFrame[c] = BitmapFrame.Create(src);
        }
        WriteObject(outFrame);
    }
}
+1  A: 

It seems that the error you're getting on the FromStream call might be because the image format is invalid. This could be for many reasons and since I'm not sure exactly how this Cmdlet is being used I will make an assumption:

I may be incorrect here, but since you're passing in an array of BitMapFrame's, I'm wondering if the ProcessRecord is being called once for each array element. The only way to truly tell is to see how you're Cmdlet is being invoked. For example, if your BitMap parameter is coming from the pipeline then there is a good chance that ProcessRecord is being called once for each BitMapFrame in the array.

Does that make sense?

Scott Saad
this is the command I put in command prompt for it: Import-Image E:\RawConvert\lenna.arf | ConvertTo-Rotate 90 | Export-Image E:\RawConvert\rotate.jpgit gets all the frames into an array in the import one, sends to the rotate cmdlet (with 90 deg) with the frames being sent thru pipeline. but I thought since the only loop was within the ProcessRecord it would only call it once?what's wrong with my image format?
dabonz413
I was just curious how the Cmdlet is being called because if it's part of the pipeline and foreach-object is also being used then ProcessRecord gets called every time. If this were the case, the image format would be wrong and it would make since why FromStream is failing (i.e. it only has part of the BitMapFrame).
Scott Saad
Just to make sure, can you validate that when you run the command like you've indicated above that your ConvertTo-Rotate90 Cmdlet is being called ONLY once? It seems that there is a very good chance that it's being called once for each element in the array that the Import-Image passes to it.
Scott Saad
I have text that prints out at the beginning of the ProcessRecord for the cmdlet and that only shows once...
dabonz413