226 lines
5.9 KiB
C#
226 lines
5.9 KiB
C#
//
|
|
// PictureObjectModel.cs - provides an ObjectModel for manipulating image files
|
|
//
|
|
// Author:
|
|
// Michael Becker <alcexhim@gmail.com>
|
|
//
|
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using MBS.Framework.Drawing;
|
|
|
|
namespace UniversalEditor.ObjectModels.Multimedia.Picture
|
|
{
|
|
/// <summary>
|
|
/// Provides an <see cref="ObjectModel" /> for manipulating image files.
|
|
/// </summary>
|
|
public class PictureObjectModel : ObjectModel
|
|
{
|
|
public class PictureObjectModelCollection
|
|
: System.Collections.ObjectModel.Collection<PictureObjectModel>
|
|
{
|
|
}
|
|
|
|
private PositionVector2 lastAddedLocation = new PositionVector2(0, 0);
|
|
|
|
public List<Color> ColorMap { get; } = new List<Color>();
|
|
|
|
public void SetPixel(Color color)
|
|
{
|
|
if (lastAddedLocation.X >= mvarWidth && lastAddedLocation.Y >= mvarHeight)
|
|
{
|
|
throw new InvalidOperationException("Out of image space. Try resizing the image");
|
|
}
|
|
|
|
if (lastAddedLocation.X >= mvarWidth)
|
|
{
|
|
lastAddedLocation.X = 0;
|
|
lastAddedLocation.Y++;
|
|
}
|
|
|
|
SetPixel(color, (int)lastAddedLocation.X, (int)lastAddedLocation.Y);
|
|
lastAddedLocation.X++;
|
|
}
|
|
[System.Diagnostics.DebuggerNonUserCode]
|
|
public void SetPixel(Color color, int x, int y)
|
|
{
|
|
if (x >= mvarWidth || y >= mvarHeight)
|
|
{
|
|
throw new InvalidOperationException("Out of image space. Try resizing the image");
|
|
}
|
|
|
|
int index = (x + (y * mvarWidth)) * 4;
|
|
bitmapData[index] = (byte)(color.R * 255);
|
|
bitmapData[index + 1] = (byte)(color.G * 255);
|
|
bitmapData[index + 2] = (byte)(color.B * 255);
|
|
bitmapData[index + 3] = (byte)(color.A * 255);
|
|
|
|
int realIndex = (int)(index / 4);
|
|
bitmapDataSet[realIndex] = true;
|
|
}
|
|
public void ClearPixel(int x, int y)
|
|
{
|
|
int index = (int)((lastAddedLocation.X + (lastAddedLocation.Y * mvarWidth)) * 4);
|
|
bitmapData[index] = 0;
|
|
bitmapData[index + 1] = 0;
|
|
bitmapData[index + 2] = 0;
|
|
bitmapData[index + 3] = 0;
|
|
|
|
int realIndex = (int)(index / 4);
|
|
bitmapDataSet[realIndex] = false;
|
|
}
|
|
public Color GetPixel(int x, int y)
|
|
{
|
|
if (x >= mvarWidth || y >= mvarHeight)
|
|
{
|
|
throw new InvalidOperationException("Out of image space. Try resizing the image");
|
|
}
|
|
|
|
int index = (x + (y * mvarWidth)) * 4;
|
|
int realIndex = (int)(index / 4);
|
|
if (bitmapDataSet[realIndex])
|
|
{
|
|
byte a = bitmapData[index + 0];
|
|
byte r = bitmapData[index + 1];
|
|
byte g = bitmapData[index + 2];
|
|
byte b = bitmapData[index + 3];
|
|
|
|
Color color = Color.FromRGBAByte(a, r, g, b);
|
|
return color;
|
|
}
|
|
return Color.Empty;
|
|
}
|
|
public Color GetPixel(PositionVector2 point)
|
|
{
|
|
return GetPixel((int)point.X, (int)point.Y);
|
|
}
|
|
|
|
private byte[] bitmapData = new byte[] { 0, 0, 0, 0 };
|
|
private bool[] bitmapDataSet = new bool[] { false };
|
|
|
|
public PictureObjectModel()
|
|
{
|
|
}
|
|
public PictureObjectModel(int width, int height)
|
|
{
|
|
bitmapData = new byte[(width * height) * 4];
|
|
bitmapDataSet = new bool[(width * height) * 4];
|
|
|
|
mvarWidth = width;
|
|
mvarHeight = height;
|
|
}
|
|
|
|
private int mvarWidth = 1;
|
|
public int Width
|
|
{
|
|
get { return mvarWidth; }
|
|
set
|
|
{
|
|
mvarWidth = value;
|
|
bitmapData = new byte[mvarWidth * mvarHeight * 4];
|
|
bitmapDataSet = new bool[mvarWidth * mvarHeight];
|
|
}
|
|
}
|
|
private int mvarHeight = 1;
|
|
public int Height
|
|
{
|
|
get { return mvarHeight; }
|
|
set
|
|
{
|
|
mvarHeight = value;
|
|
bitmapData = new byte[mvarWidth * mvarHeight * 4];
|
|
bitmapDataSet = new bool[mvarWidth * mvarHeight];
|
|
}
|
|
}
|
|
|
|
|
|
protected override ObjectModelReference MakeReferenceInternal()
|
|
{
|
|
ObjectModelReference omr = base.MakeReferenceInternal();
|
|
omr.Title = "Picture";
|
|
omr.Path = new string[] { "Multimedia", "Picture", "Single Picture" };
|
|
return omr;
|
|
}
|
|
|
|
public override void Clear()
|
|
{
|
|
ColorMap.Clear();
|
|
Width = 1;
|
|
Height = 1;
|
|
}
|
|
public override void CopyTo(ObjectModel destination)
|
|
{
|
|
PictureObjectModel clone = (destination as PictureObjectModel);
|
|
clone.Width = mvarWidth;
|
|
clone.Height = mvarHeight;
|
|
clone.bitmapData = (bitmapData.Clone() as byte[]);
|
|
clone.bitmapDataSet = (bitmapDataSet.Clone() as bool[]);
|
|
}
|
|
|
|
public byte[] ToByteArray()
|
|
{
|
|
// memory goes from left to right, top to bottom
|
|
byte[] data = new byte[mvarWidth * mvarHeight * 4];
|
|
int i = 0;
|
|
for (int h = 0; h < mvarHeight; h++)
|
|
{
|
|
for (int w = 0; w < mvarWidth; w++)
|
|
{
|
|
int index = (w + (h * mvarWidth)) * 4;
|
|
int realIndex = (int)(index / 4);
|
|
if (bitmapDataSet[realIndex])
|
|
{
|
|
data[i + 3] = bitmapData[index + 3];
|
|
data[i + 2] = bitmapData[index + 0];
|
|
data[i + 1] = bitmapData[index + 1];
|
|
data[i + 0] = bitmapData[index + 2];
|
|
}
|
|
i += 4;
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
public static PictureObjectModel FromByteArray(byte[] data, int width, int height)
|
|
{
|
|
if (width == 0 || height == 0) return null;
|
|
|
|
PictureObjectModel pic = new PictureObjectModel();
|
|
pic.Width = width;
|
|
pic.Height = height;
|
|
|
|
// memory goes from left to right, top to bottom
|
|
int i = 0;
|
|
for (int h = 0; h < height; h++)
|
|
{
|
|
for (int w = 0; w < width; w++)
|
|
{
|
|
byte b = data[i];
|
|
byte g = data[i + 1];
|
|
byte r = data[i + 2];
|
|
byte a = data[i + 3];
|
|
|
|
Color color = Color.FromRGBAByte(r, g, b, a);
|
|
pic.SetPixel(color, w, h);
|
|
|
|
i += 4;
|
|
}
|
|
}
|
|
return pic;
|
|
}
|
|
}
|
|
}
|