none
How to left pad a 2 dimensional byte array with leading zeros in C# RRS feed

  • Question

  • I have a 2 dimensional byte array of a bitmap pixel data that I need to send to a thermal printer using ESC/POS via comport. I can do this successfully. However, I need to shift the printed image to the right. Center justify, Right justify, HT, and all other ESC/POS commands have no effect due to the command used to print the bitmap (DC2 * r n [d1.....dn]). I wish to left pad the array of bytes containing the bitmap in order to shift the printed image to the right. Below are my code lines to print bitmap

            private void Print_Bipmap()

            {

                int x;

                int y;

                int i;

                int RowBytes;

                byte n;

                Color Pixels;

                byte[,] ImageArray = new byte[bitmap.Width, bitmap.Height];

                

                // Calculate output size

                RowBytes = (bitmap.Width + 7) / 8;

                // Generate body of array

                for (y = 0; y < bitmap.Height; y++)

                { // Each row...

                    for (x = 0; x < (bitmap.Width / 8); x++)

                    { // Each 8-pixel block within row...

                        ImageArray[x, y] = 0;

                        for (n = 0; n < 8; n++)

                        { // Each pixel within block...

                            Pixels = bitmap.GetPixel(x * 8 + n, y);

                            if (Pixels.GetBrightness() < 0.5)

                            {

                                ImageArray[x, y] += (byte)(1 << (7 - n));

                            }

                        }

                    }

                }

                comport_writeByte(18); //DC2

                comport_writeByte(42); //*

                comport_writeByte((byte)bitmap.Height); //r

                comport_writeByte((byte)RowBytes); //n

                for (y = 0; y < bitmap.Height; y++)

                {

                    for (x = 0; x < RowBytes; x++)

                    {

                                 comport_writeByte(ImageArray[x, y]); //[d1 ..... dn]

                    }

                }

            }

    How do I left pad the 2 dimensional array (ImageArray[x, y])? Many thanks in advance.




    • Edited by Topa 1 Friday, March 2, 2018 4:30 AM
    Thursday, March 1, 2018 6:51 PM

Answers

  • If you want the image shifted to the right, then you need to LEFT pad the array.

    The easiest way to do this is to create your ImageArray as the size you really want it, including the margins, then write the bits in the proper location.  Don't think of it as left-padding, think of positioning the image in the blank canvas.  So, something like:

        ImageArray[x+offset,y] += (byte)(1 <<(7-n));


    Tim Roberts, Driver MVP Providenza & Boekelheide, Inc.

    • Marked as answer by Topa 1 Saturday, March 3, 2018 4:32 AM
    Thursday, March 1, 2018 7:59 PM
  • I think I would say the same as Tim except I assume it is a constant series of bytes; in other words, you are just adding the exact same bytes to the beginning of each row. So I think you can just go through and precede each row with the same series of bytes.


    Sam Hobbs
    SimpleSamples.Info

    • Marked as answer by Topa 1 Saturday, March 3, 2018 4:32 AM
    Saturday, March 3, 2018 3:52 AM
  • Many thanks to everyone who responded. I am now able to have the image shifted to the right. 

    Note should be made that the printer's endianess is BIG endian hence the code line:

    ImageArray[x, y] += (byte)(1 << (7 - n));

    The printer expects data in the order DC2 * r n [d1 ..... dn], to this end padding may not be moved as a separate piece of data.

    Tim's suggestion i.e "to create your ImageArray as the size you really want it, including the margins, then write the bits in the proper location.  Don't think of it as left-padding, think of positioning the image in the blank canvas" seems to be the way to go. However, I added 10 bytes to the output rows increasing the size to 39 bytes by changing the line:

    RowBytes = (bitmap.Width + 7) / 8;

    to:

    RowBytes = (bitmap.Width + 87) / 8;
    I then sent the data to the printer subtracting the image row bytes from the output size thus:
    for (y = 0; y < bitmap.Height; y++)
    {
      for (x = 0; x < RowBytes; x++)
      {
        comport_writeByte(ImageArray[40 - x, y]); //[d1 ..... dn]
      }
    }

    In addition, I find that the endianess needed to change to small endian i.e LSB first thus:

    From

    ImageArray[x, y] += (byte)(1 << (7 - n));
    to
    ImageArray[x, y] += (byte)(1 << n);







    • Marked as answer by Topa 1 Saturday, March 3, 2018 4:38 AM
    • Edited by Topa 1 Saturday, March 3, 2018 4:49 PM
    Saturday, March 3, 2018 3:42 AM

All replies

  • If you want the image shifted to the right, then you need to LEFT pad the array.

    The easiest way to do this is to create your ImageArray as the size you really want it, including the margins, then write the bits in the proper location.  Don't think of it as left-padding, think of positioning the image in the blank canvas.  So, something like:

        ImageArray[x+offset,y] += (byte)(1 <<(7-n));


    Tim Roberts, Driver MVP Providenza & Boekelheide, Inc.

    • Marked as answer by Topa 1 Saturday, March 3, 2018 4:32 AM
    Thursday, March 1, 2018 7:59 PM
  • Maybe like this:

       for (y = 0; y < bitmapheight; y++)

       {

          for ( i = 0; i < some_shift; i++) Comport_writeByte( 0 );

          for (x = 0; x < bitmapwidth; x++)

          {

            Comport_writeByte(ImageArray[x, y]); // [d1 .... dn]

          }

       }

    Perhaps you should also adjust (increase) the sent value of ‘n’.

     


    • Edited by Viorel_MVP Thursday, March 1, 2018 8:07 PM
    Thursday, March 1, 2018 8:07 PM
  • First, you can create another array with the larger bounds for the first dimension and then add the padding and then copy the first array. There are some possibilities in how to concatenate data from two Byte arrays into one Byte array?. including Array.CopyTo Method (Array, Int32) and List(T).AddRange Method (IEnumerable(T)) (System.Collections.Generic). Also see [C#] Two Easy Tricks to Play with Byte Array Using Buffer.BlockCopy – Tyler Fang's Blog.


    Sam Hobbs
    SimpleSamples.Info

    Thursday, March 1, 2018 9:26 PM
  • Many thanks Tim. How do I go about this in relation to my edited code?
    Friday, March 2, 2018 4:39 AM
  • Many thanks for your response Viorel. Could you please be more elaborate? I can't get a hang of this. Following your suggestion, the printed image was gibberish.
    Please note the edit.
    Friday, March 2, 2018 4:40 AM
  • @Sam. I am working with a 2 dimensional array of bytes (rows and columns) containing pixel data for a bitmap image. The suggested solutions are not applicable.
    Saturday, March 3, 2018 1:02 AM
  • Read my response again and this time assume I know that. Yes, rows and columns. I am not an idiot.

    Many years ago back in 16-bit Windows and 80386 processors and before the internet was available for getting help like here I wrote a printer device driver. Without going into too many details, to support Landscape,  I had to be able to take the bitmap from Windows and rotate it and that had to be done as fast as possible, or at least I thought so. So that portion of the device driver I wrote using assembler. It moved each bit to separate bytes to get the image rotated. I had to think about it for three days but then it worked perfectly.

    Excuse me if I misunderstand but I really think I do. I think those references I provided make it easy and efficient. I am confident you are smart enough to figure it out. Please, at least assume I understand the requirements before saying it won't work.

    In the C language there are a couple of ways of implementing two-dimensional arrays and each one arranges the data differently. I understand the concept of data being contiguous and non-contiguous.

    In a bitmap the data for each row is contiguous, right? The second row is in memory immediately after the first row, such that each column is separated from the following and preceding one by the size of the row.

    In the solution from Viorel_ (I was going to say Viorel_'s solution but that looks strange) there is an outer loop for height and two inner loops, one that adds the padding and the one for each row. My assumption is that the padding can all be moved as one piece of constant data and the row for the image can then all be moved as one piece of memory and the rows get stacked one after another. Just zap the data around with ease for both you and the computer. You can do it. It is not complicated.



    Sam Hobbs
    SimpleSamples.Info

    Saturday, March 3, 2018 2:10 AM
  • Many thanks to everyone who responded. I am now able to have the image shifted to the right. 

    Note should be made that the printer's endianess is BIG endian hence the code line:

    ImageArray[x, y] += (byte)(1 << (7 - n));

    The printer expects data in the order DC2 * r n [d1 ..... dn], to this end padding may not be moved as a separate piece of data.

    Tim's suggestion i.e "to create your ImageArray as the size you really want it, including the margins, then write the bits in the proper location.  Don't think of it as left-padding, think of positioning the image in the blank canvas" seems to be the way to go. However, I added 10 bytes to the output rows increasing the size to 39 bytes by changing the line:

    RowBytes = (bitmap.Width + 7) / 8;

    to:

    RowBytes = (bitmap.Width + 87) / 8;
    I then sent the data to the printer subtracting the image row bytes from the output size thus:
    for (y = 0; y < bitmap.Height; y++)
    {
      for (x = 0; x < RowBytes; x++)
      {
        comport_writeByte(ImageArray[40 - x, y]); //[d1 ..... dn]
      }
    }

    In addition, I find that the endianess needed to change to small endian i.e LSB first thus:

    From

    ImageArray[x, y] += (byte)(1 << (7 - n));
    to
    ImageArray[x, y] += (byte)(1 << n);







    • Marked as answer by Topa 1 Saturday, March 3, 2018 4:38 AM
    • Edited by Topa 1 Saturday, March 3, 2018 4:49 PM
    Saturday, March 3, 2018 3:42 AM
  • I think I would say the same as Tim except I assume it is a constant series of bytes; in other words, you are just adding the exact same bytes to the beginning of each row. So I think you can just go through and precede each row with the same series of bytes.


    Sam Hobbs
    SimpleSamples.Info

    • Marked as answer by Topa 1 Saturday, March 3, 2018 4:32 AM
    Saturday, March 3, 2018 3:52 AM