You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

270 lines
8.5 KiB

/*
DataMatrix.Net
DataMatrix.Net - .net library for decoding DataMatrix codes.
Copyright (C) 2009/2010 Michael Faschinger
This library 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.0 of the License, or (at your option) any later version.
You can also redistribute and/or modify it under the terms of the
GNU Lesser General Public License as published by the Free Software
Foundation; either version 3.0 of the License or (at your option)
any later version.
This library 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 or the GNU Lesser General Public License
for more details.
You should have received a copy of the GNU General Public
License and the GNU Lesser General Public License along with this
library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Contact: Michael Faschinger - michfasch@gmx.at
*/
using System;
namespace DataMatrix.net
{
internal class DmtxImage
{
#region Fields
int _rowPadBytes;
#endregion
#region Constructor
internal DmtxImage(byte[] pxl, int width, int height, DmtxPackOrder pack)
{
this.BitsPerChannel = new int[4];
this.ChannelStart = new int[4];
if (pxl == null || width < 1 || height < 1)
{
throw new ArgumentException("Cannot create image of size null");
}
this.Pxl = pxl;
this.Width = width;
this.Height = height;
this.PixelPacking = pack;
this.BitsPerPixel = DmtxCommon.GetBitsPerPixel(pack);
this.BytesPerPixel = this.BitsPerPixel / 8;
this._rowPadBytes = 0;
this.RowSizeBytes = this.Width * this.BytesPerPixel + this._rowPadBytes;
this.ImageFlip = DmtxFlip.DmtxFlipNone;
/* Leave channelStart[] and bitsPerChannel[] with zeros from calloc */
this.ChannelCount = 0;
switch (pack)
{
case DmtxPackOrder.DmtxPackCustom:
break;
case DmtxPackOrder.DmtxPack1bppK:
throw new ArgumentException("Cannot create image: not supported pack order!");
case DmtxPackOrder.DmtxPack8bppK:
SetChannel(0, 8);
break;
case DmtxPackOrder.DmtxPack16bppRGB:
case DmtxPackOrder.DmtxPack16bppBGR:
case DmtxPackOrder.DmtxPack16bppYCbCr:
SetChannel(0, 5);
SetChannel(5, 5);
SetChannel(10, 5);
break;
case DmtxPackOrder.DmtxPack24bppRGB:
case DmtxPackOrder.DmtxPack24bppBGR:
case DmtxPackOrder.DmtxPack24bppYCbCr:
case DmtxPackOrder.DmtxPack32bppRGBX:
case DmtxPackOrder.DmtxPack32bppBGRX:
SetChannel(0, 8);
SetChannel(8, 8);
SetChannel(16, 8);
break;
case DmtxPackOrder.DmtxPack16bppRGBX:
case DmtxPackOrder.DmtxPack16bppBGRX:
SetChannel(0, 5);
SetChannel(5, 5);
SetChannel(10, 5);
break;
case DmtxPackOrder.DmtxPack16bppXRGB:
case DmtxPackOrder.DmtxPack16bppXBGR:
SetChannel(1, 5);
SetChannel(6, 5);
SetChannel(11, 5);
break;
case DmtxPackOrder.DmtxPack32bppXRGB:
case DmtxPackOrder.DmtxPack32bppXBGR:
SetChannel(8, 8);
SetChannel(16, 8);
SetChannel(24, 8);
break;
case DmtxPackOrder.DmtxPack32bppCMYK:
SetChannel(0, 8);
SetChannel(8, 8);
SetChannel(16, 8);
SetChannel(24, 8);
break;
default:
throw new ArgumentException("Cannot create image: Invalid Pack Order");
}
}
#endregion
#region Methods
internal bool SetChannel(int channelStart, int bitsPerChannel)
{
if (this.ChannelCount >= 4) /* IMAGE_MAX_CHANNEL */
return false;
/* New channel extends beyond pixel data */
this.BitsPerChannel[this.ChannelCount] = bitsPerChannel;
this.ChannelStart[this.ChannelCount] = channelStart;
(this.ChannelCount)++;
return true;
}
internal int GetByteOffset(int x, int y)
{
if (this.ImageFlip == DmtxFlip.DmtxFlipX)
{
throw new ArgumentException("DmtxFlipX is not an option!");
}
if (!ContainsInt(0, x, y))
return DmtxConstants.DmtxUndefined;
if (this.ImageFlip == DmtxFlip.DmtxFlipY)
return (y * this.RowSizeBytes + x * this.BytesPerPixel);
return ((this.Height - y - 1) * this.RowSizeBytes + x * this.BytesPerPixel);
}
internal bool GetPixelValue(int x, int y, int channel, ref int value)
{
if (channel >= this.ChannelCount)
{
throw new ArgumentException("Channel greater than channel count!");
}
int offset = GetByteOffset(x, y);
if (offset == DmtxConstants.DmtxUndefined)
{
return false;
}
switch (this.BitsPerChannel[channel])
{
case 1:
break;
case 5:
break;
case 8:
if (this.ChannelStart[channel] % 8 != 0 || this.BitsPerPixel % 8 != 0)
{
throw new Exception("Error getting pixel value");
}
value = this.Pxl[offset + channel];
break;
}
return true;
}
internal bool SetPixelValue(int x, int y, int channel, byte value)
{
if (channel >= this.ChannelCount)
{
throw new ArgumentException("Channel greater than channel count!");
}
int offset = GetByteOffset(x, y);
if (offset == DmtxConstants.DmtxUndefined)
{
return false;
}
switch (this.BitsPerChannel[channel])
{
case 1:
break;
case 5:
break;
case 8:
if (this.ChannelStart[channel] % 8 != 0 || this.BitsPerPixel % 8 != 0)
{
throw new Exception("Error getting pixel value");
}
this.Pxl[offset + channel] = value;
break;
}
return true;
}
internal bool ContainsInt(int margin, int x, int y)
{
if (x - margin >= 0 && x + margin < this.Width &&
y - margin >= 0 && y + margin < this.Height)
return true;
return false;
}
internal bool ContainsFloat(double x, double y)
{
if (x >= 0.0 && x < this.Width && y >= 0.0 && y < this.Height)
{
return true;
}
return false;
}
#endregion
#region Properties
internal int Width { get; set; }
internal int Height { get; set; }
internal DmtxPackOrder PixelPacking { get; set; }
internal int BitsPerPixel { get; set; }
internal int BytesPerPixel { get; set; }
internal int RowPadBytes
{
get { return _rowPadBytes; }
set
{
_rowPadBytes = value;
this.RowSizeBytes = this.Width * (this.BitsPerPixel / 8) + this._rowPadBytes;
}
}
internal int RowSizeBytes { get; set; }
internal DmtxFlip ImageFlip { get; set; }
internal int ChannelCount { get; set; }
internal int[] ChannelStart { get; set; }
internal int[] BitsPerChannel { get; set; }
internal byte[] Pxl { get; set; }
#endregion
}
}