Section 4 - A Pseudo-Datamatrix Class (Optional)
6B.4.1 A Strategy for the Solution Barcode Classes
We are ready for the actual class or classes that will be derived from BarcodeIO and contain, as an internal member object, a BarcodeImage. Before we jump in and start creating this class, let's think about what its purpose is? Are we ready to implement a specific barcode symbology like Datamatrix, or pdf-417?
Maybe not. A lot of the things we want to do next would apply to any symbology. So a good design should subclass from BarcodeIO with an embedded string and BarcodeImage members into a new base class called ImageReaderWriter that does things like print a label and read in a label. What we should not be doing at this level of abstraction is converting the image to text or vice versa, since that is symbology-dependent. From the recommended ImageReaderWriter, we would subclass specific symbology classes. When you think about it, you might ask what to do with the two interface methods, generateImageFromText() and translateImageToText(). They don't quite have an obvious place in ImageReaderWriter, since we need a symbology for their implementation. However, we can give abstract and generic shells for these methods and require the subclasses do the implementation.
Anyway, the structure should be something like this:

The word "implements" above is Java-speak, and it is used because I made this scruffy picture originally for my CIS 27B class, way back. Here it means that we would subclass BarcodeIO, defining some, but not all, virtual functions. This is what it should look like. What we will do, however, is skip the general base class ImageReaderWriter and go directly, instead, to DataMatrix. This is to keep the example and assignment manageable. So here is the diagram we will follow:

6B.4.2 The Target Class, DataMatrix
This class is a pseudo Datamatrix data structure, not a true Datamatrix implementation, because it does not contain any of the error correction or encoding in a real Datamatrix. However, it does have the 2D array format and a left and bottom BLACK edge and an alternating right and top BLACK-WHITE pattern as seen in prior pages.
DataMatrix Data
- (public) static const char BLACK_CHAR = '*';
- (public) static const char WHITE_CHAR = ' ';
- (private) BarcodeImage image - a single internal copy of any image scanned-in OR passed-into the constructor OR created by BarcodeIO's generateImageFromText().
- (private) string text - a single internal copy of any text read-in OR passed-into the constructor OR created by BarcodeIO's translateImageToText().
- (private) int actualWidth and actualHeight - two ints that are typically less than BarcodeImage::MAX_WIDTH and BarcodeImage::MAX_HEIGHT which represent the actual portion of the BarcodeImage that has real signal. This is dependent on the data in the image and can change as the image changes through mutators.
Note that there is no deep data here.
DataMatrix Methods
- Constructors.
- DataMatrix(const string & text = "") - constructs an empty (white) image and a specified (or default) text value. The initial image should be all white, but actualWidth and actualHeight will start at 0, so it won't really matter what's in this default image, in practice.
- DataMatrix(BarcodeImage image) - sets the image but leaves the text at any default value. Call scan() and avoid duplication of code here.
- readText(String text) - a mutator for text. Like the constructor; in fact it is called by the constructor.
- scan(BarcodeImage image) - a mutator for image. Like the constructor; in fact it is called by the constructor. Since there is no deep data in this class, the main thing is to make sure that the BarcodeImage member is correctly copied. This is easy because we have an assignment operator overloaded in that class. In addition to storing the BarcodeImage (which is trivial), we need to compute the actualWidth and actualHeight.
- Accessors for actualWidth and actualHeight but no mutators! (why?)
- private int computeSignalWidth() and private int computeSignalHeight() - Assuming that the image is correctly situated in the lower-left corner of BarcodeImage's bool array, these methods use the "spine" (Closed Limitation Line) of the array (left and bottom BLACK) to determine the actual size - it returns the int values as functional returns.
- Implementation of all BarcodeIO virtual methods.
Other Considerations for DataMatrix
- displayImageToConsole() should display only the relevant portion of the image, clipping the excess blank/white from the top and right. Also, show a border as in:
------------------------------------ |* * * * * * * * * * * * * * * * * | |* *| |**** * ***** **** **** ******** | |* *** ***************** ********| |* * ** * * * * * ** | |* * * * ** * * * ****| |* * * ** * * * * ** * | |** * *** ***** ** * * **| |**** * **** ** * * * * * | |**********************************| ------------------------------------
As you can tell, the implementation of this is going to be your assignment this week. I have provided some significant structure and also a lot of useful code that you can steal from the TwoDimImage class.
Do this one step-at-a-time, following my outline and also digesting what you are doing and why you are doing it at each juncture. I am here for questions, as usual.
6B.4.3 A Sample Main()
Here is a main() to use as a test of your code. You should create simpler main()s as you work your way up to this:
int main() { string sImageIn[13] = { " ", " ", " ", "* * * * * * * * * * * * * * * * * * * * * * * * * * * ", "* *", "********** *** *********** * ****** **** ********* ", "* *********** ****************************************", "* * * * * * * * * * * ", "* * * ** ** * * * *** *** * * * ** *", "* *** *** ** * ******** * ** *** *** * * ", "** ** * * * * *** *** *", "*** * * * *** ** *** * * ** * *** * ** * ** ", "******************************************************" }; string sImageIn_2[12] = { " ", " ", "* * * * * * * * * * * * * * * * * * * ", "* *", "**** * * ******** ** ****** *** **** ", "* ******************* ********** **", "* *** * * * * * * * ** ", "* * * * * * ** * **", "** * * **** * ** ***** * * * * ", "* * * * * * ** ****", "* * * * **** * * *** * * * ** ", "**************************************" }; BarcodeImage bc(sImageIn, 13); DataMatrix dm(bc); // First secret message dm.translateImageToText(); dm.displayTextToConsole(); dm.displayImageToConsole(); // second secret message bc = BarcodeImage(sImageIn_2, 12); dm.scan(bc); dm.translateImageToText(); dm.displayTextToConsole(); dm.displayImageToConsole(); // create your own message dm.readText("CS 2B rocks more than Zeppelin"); dm.generateImageFromText(); dm.displayTextToConsole(); dm.displayImageToConsole(); return 0; }