[SCM] Multi-format 1D/2D barcode image processing library branch, upstream, updated. 3b22568664b0c0017ea793fd3cf5fde433e95717

srowen srowen at 59b500cc-1b3d-0410-9834-0bbf25fbcc57
Wed Jun 30 15:30:11 UTC 2010


The following commit has been merged in the upstream branch:
commit 39ad0a4d87d592f3de98101bb05855348c78494e
Author: srowen <srowen at 59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Date:   Tue Mar 30 22:53:34 2010 +0000

    Issue 361
    
    git-svn-id: http://zxing.googlecode.com/svn/trunk@1268 59b500cc-1b3d-0410-9834-0bbf25fbcc57

diff --git a/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java b/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java
index c55481c..de54e60 100755
--- a/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java
+++ b/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java
@@ -26,7 +26,7 @@ import com.google.zxing.client.android.R;
 import com.google.zxing.client.result.AddressBookParsedResult;
 import com.google.zxing.client.result.ParsedResult;
 import com.google.zxing.client.result.ResultParser;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 
 import android.app.Activity;
 import android.content.Intent;
@@ -53,6 +53,8 @@ final class QRCodeEncoder {
 
   private static final String TAG = "QRCodeEncoder";
 
+  private static final int WHITE = 0xFFFFFFFF;
+
   private final Activity activity;
   private String contents;
   private String displayContents;
@@ -327,17 +329,18 @@ final class QRCodeEncoder {
     @Override
     public void run() {
       try {
-        ByteMatrix result = new MultiFormatWriter().encode(contents, format,
+        BitMatrix result = new MultiFormatWriter().encode(contents, format,
             pixelResolution, pixelResolution);
         int width = result.getWidth();
         int height = result.getHeight();
-        byte[][] array = result.getArray();
         int[] pixels = new int[width * height];
+        // All are 0, or black, by default
         for (int y = 0; y < height; y++) {
+          int offset = y * width;
           for (int x = 0; x < width; x++) {
-            int grey = array[y][x] & 0xff;
-            // pixels[y * width + x] = (0xff << 24) | (grey << 16) | (grey << 8) | grey;
-            pixels[y * width + x] = 0xff000000 | (0x00010101 * grey);
+            if (!result.get(x, y)) {
+              pixels[offset + x] = WHITE;
+            }
           }
         }
 
diff --git a/core/src/com/google/zxing/MultiFormatWriter.java b/core/src/com/google/zxing/MultiFormatWriter.java
index 3ec8979..297b79e 100644
--- a/core/src/com/google/zxing/MultiFormatWriter.java
+++ b/core/src/com/google/zxing/MultiFormatWriter.java
@@ -16,7 +16,7 @@
 
 package com.google.zxing;
 
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 import com.google.zxing.oned.Code128Writer;
 import com.google.zxing.oned.Code39Writer;
 import com.google.zxing.oned.EAN13Writer;
@@ -34,13 +34,13 @@ import java.util.Hashtable;
  */
 public final class MultiFormatWriter implements Writer {
 
-  public ByteMatrix encode(String contents, BarcodeFormat format, int width,
+  public BitMatrix encode(String contents, BarcodeFormat format, int width,
       int height) throws WriterException {
 
     return encode(contents, format, width, height, null);
   }
 
-  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height,
+  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
       Hashtable hints) throws WriterException {
 
     Writer writer;
diff --git a/core/src/com/google/zxing/Writer.java b/core/src/com/google/zxing/Writer.java
index 221d5ad..6474ca7 100644
--- a/core/src/com/google/zxing/Writer.java
+++ b/core/src/com/google/zxing/Writer.java
@@ -16,7 +16,7 @@
 
 package com.google.zxing;
 
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 
 import java.util.Hashtable;
 
@@ -36,7 +36,7 @@ public interface Writer {
    * @param height The preferred height in pixels
    * @return The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
    */
-  ByteMatrix encode(String contents, BarcodeFormat format, int width, int height)
+  BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
       throws WriterException;
 
   /**
@@ -48,7 +48,7 @@ public interface Writer {
    * @param hints Additional parameters to supply to the encoder
    * @return The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
    */
-  ByteMatrix encode(String contents, BarcodeFormat format, int width, int height, Hashtable hints)
+  BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Hashtable hints)
       throws WriterException;
 
 }
diff --git a/core/src/com/google/zxing/common/BitArray.java b/core/src/com/google/zxing/common/BitArray.java
index bab2a3a..6c150bf 100644
--- a/core/src/com/google/zxing/common/BitArray.java
+++ b/core/src/com/google/zxing/common/BitArray.java
@@ -28,12 +28,14 @@ public final class BitArray {
   // resulting binary at runtime on Android. If we find a solution to this, these should be changed
   // back to private.
   public int[] bits;
-  public final int size;
+  public int size;
+
+  public BitArray() {
+    this.size = 0;
+    this.bits = new int[1];
+  }
 
   public BitArray(int size) {
-    if (size < 1) {
-      throw new IllegalArgumentException("size must be at least 1");
-    }
     this.size = size;
     this.bits = makeArray(size);
   }
@@ -42,6 +44,18 @@ public final class BitArray {
     return size;
   }
 
+  public int getSizeInBytes() {
+    return (size + 7) >> 3;
+  }
+
+  private void ensureCapacity(int size) {
+    if (size > bits.length << 5) {
+      int[] newBits = makeArray(size);
+      System.arraycopy(bits, 0, newBits, 0, bits.length);
+      this.bits = newBits;
+    }
+  }
+
   /**
    * @param i bit to get
    * @return true iff bit i is set
@@ -130,6 +144,69 @@ public final class BitArray {
     return true;
   }
 
+  public void appendBit(boolean bit) {
+    ensureCapacity(size + 1);
+    if (bit) {
+      bits[size >> 5] |= (1 << (size & 0x1F));
+    }
+    size++;
+  }
+
+  /**
+   * Appends the least-significant bits, from value, in order from most-significant to
+   * least-significant. For example, appending 6 bits from 0x000001E will append the bits
+   * 0, 1, 1, 1, 1, 0 in that order.
+   */
+  public void appendBits(int value, int numBits) {
+    if (numBits < 0 || numBits > 32) {
+      throw new IllegalArgumentException("Num bits must be between 0 and 32");
+    }
+    ensureCapacity(size + numBits);
+    for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) {
+      appendBit(((value >> (numBitsLeft - 1)) & 0x01) == 1);
+    }
+  }
+
+  public void appendBitArray(BitArray other) {
+    int otherSize = other.getSize();
+    ensureCapacity(size + otherSize);
+    for (int i = 0; i < otherSize; i++) {
+      appendBit(other.get(i));
+    }
+  }
+
+  public void xor(BitArray other) {
+    if (bits.length != other.bits.length) {
+      throw new IllegalArgumentException("Sizes don't match");
+    }
+    for (int i = 0; i < bits.length; i++) {
+      // The last byte could be incomplete (i.e. not have 8 bits in
+      // it) but there is no problem since 0 XOR 0 == 0.
+      bits[i] ^= other.bits[i];
+    }
+  }
+
+  /**
+   *
+   * @param bitOffset first bit to start writing
+   * @param array array to write into. Bytes are written most-significant byte first. This is the opposite
+   *  of the internal representation, which is exposed by {@link #getBitArray()}
+   * @param offset position in array to start writing
+   * @param numBytes how many bytes to write
+   */
+  public void toBytes(int bitOffset, byte[] array, int offset, int numBytes) {
+    for (int i = 0; i < numBytes; i++) {
+      int theByte = 0;
+      for (int j = 0; j < 8; j++) {
+        if (get(bitOffset)) {
+          theByte |= 1 << (7 - j);
+        }
+        bitOffset++;
+      }
+      array[offset + i] = (byte) theByte;
+    }
+  }
+
   /**
    * @return underlying array of ints. The first element holds the first 32 bits, and the least
    *         significant bit is bit 0.
@@ -153,11 +230,7 @@ public final class BitArray {
   }
 
   private static int[] makeArray(int size) {
-    int arraySize = size >> 5;
-    if ((size & 0x1F) != 0) {
-      arraySize++;
-    }
-    return new int[arraySize];
+    return new int[(size + 31) >> 5];
   }
   
   public String toString() {
diff --git a/core/src/com/google/zxing/common/BitMatrix.java b/core/src/com/google/zxing/common/BitMatrix.java
index 1088db2..f1023b8 100755
--- a/core/src/com/google/zxing/common/BitMatrix.java
+++ b/core/src/com/google/zxing/common/BitMatrix.java
@@ -50,11 +50,7 @@ public final class BitMatrix {
     }
     this.width = width;
     this.height = height;
-    int rowSize = width >> 5;
-    if ((width & 0x1f) != 0) {
-      rowSize++;
-    }
-    this.rowSize = rowSize;
+    this.rowSize = (width + 31) >> 5;
     bits = new int[rowSize * height];
   }
 
@@ -163,17 +159,32 @@ public final class BitMatrix {
     return height;
   }
 
-  /**
-   * This method is for compatibility with older code. It's only logical to call if the matrix
-   * is square, so I'm throwing if that's not the case.
-   *
-   * @return row/column dimension of this matrix
-   */
-  public int getDimension() {
-    if (width != height) {
-      throw new RuntimeException("Can't call getDimension() on a non-square matrix");
+  public boolean equals(Object o) {
+    if (!(o instanceof BitMatrix)) {
+      return false;
     }
-    return width;
+    BitMatrix other = (BitMatrix) o;
+    if (width != other.width || height != other.height ||
+        rowSize != other.rowSize || bits.length != other.bits.length) {
+      return false;
+    }
+    for (int i = 0; i < bits.length; i++) {
+      if (bits[i] != other.bits[i]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public int hashCode() {
+    int hash = width;
+    hash = 31 * hash + width;
+    hash = 31 * hash + height;
+    hash = 31 * hash + rowSize;
+    for (int i = 0; i < bits.length; i++) {
+      hash = 31 * hash + bits[i];
+    }
+    return hash;
   }
 
   public String toString() {
diff --git a/core/src/com/google/zxing/common/ByteArray.java b/core/src/com/google/zxing/common/ByteArray.java
deleted file mode 100644
index 58116f0..0000000
--- a/core/src/com/google/zxing/common/ByteArray.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-/**
- * This class implements an array of unsigned bytes.
- *
- * @author dswitkin at google.com (Daniel Switkin)
- */
-public final class ByteArray {
-
-  private static final int INITIAL_SIZE = 32;
-
-  private byte[] bytes;
-  private int size;
-
-  public ByteArray() {
-    bytes = null;
-    size = 0;
-  }
-
-  public ByteArray(int size) {
-    bytes = new byte[size];
-    this.size = size;
-  }
-
-  public ByteArray(byte[] byteArray) {
-    bytes = byteArray;
-    size = bytes.length;
-  }
-
-  /**
-   * Access an unsigned byte at location index.
-   * @param index The index in the array to access.
-   * @return The unsigned value of the byte as an int.
-   */
-  public int at(int index) {
-    return bytes[index] & 0xff;
-  }
-
-  public void set(int index, int value) {
-    bytes[index] = (byte) value;
-  }
-
-  public int size() {
-    return size;
-  }
-
-  public boolean isEmpty() {
-    return size == 0;
-  }
-
-  public void appendByte(int value) {
-    if (size == 0 || size >= bytes.length) {
-      int newSize = Math.max(INITIAL_SIZE, size << 1);
-      reserve(newSize);
-    }
-    bytes[size] = (byte) value;
-    size++;
-  }
-
-  public void reserve(int capacity) {
-    if (bytes == null || bytes.length < capacity) {
-      byte[] newArray = new byte[capacity];
-      if (bytes != null) {
-        System.arraycopy(bytes, 0, newArray, 0, bytes.length);
-      }
-      bytes = newArray;
-    }
-  }
-
-  // Copy count bytes from array source starting at offset.
-  public void set(byte[] source, int offset, int count) {
-    bytes = new byte[count];
-    size = count;
-    for (int x = 0; x < count; x++) {
-      bytes[x] = source[offset + x];
-    }
-  }
-
-}
diff --git a/core/src/com/google/zxing/datamatrix/decoder/BitMatrixParser.java b/core/src/com/google/zxing/datamatrix/decoder/BitMatrixParser.java
index 849f5be..96032b4 100644
--- a/core/src/com/google/zxing/datamatrix/decoder/BitMatrixParser.java
+++ b/core/src/com/google/zxing/datamatrix/decoder/BitMatrixParser.java
@@ -33,7 +33,7 @@ final class BitMatrixParser {
    * @throws FormatException if dimension is < 10 or > 144 or not 0 mod 2
    */
   BitMatrixParser(BitMatrix bitMatrix) throws FormatException {
-    int dimension = bitMatrix.getDimension();
+    int dimension = bitMatrix.getHeight();
     if (dimension < 10 || dimension > 144 || (dimension & 0x01) != 0) {
       throw FormatException.getFormatInstance();
     }
@@ -41,7 +41,7 @@ final class BitMatrixParser {
     version = readVersion(bitMatrix);
     this.mappingBitMatrix = extractDataRegion(bitMatrix);
     // TODO(bbrown): Make this work for rectangular symbols
-    this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.getDimension());
+    this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.getHeight());
   }
 
   /**
@@ -62,7 +62,7 @@ final class BitMatrixParser {
     }
 
     // TODO(bbrown): make this work for rectangular dimensions as well.
-    int numRows = bitMatrix.getDimension();
+    int numRows = bitMatrix.getHeight();
     int numColumns = numRows;
     
     return Version.getVersionForDimensions(numRows, numColumns);
@@ -84,7 +84,7 @@ final class BitMatrixParser {
     int row = 4;
     int column = 0;
     // TODO(bbrown): Data Matrix can be rectangular, assuming square for now
-    int numRows = mappingBitMatrix.getDimension();
+    int numRows = mappingBitMatrix.getHeight();
     int numColumns = numRows;
     
     boolean corner1Read = false;
@@ -408,7 +408,7 @@ final class BitMatrixParser {
     int symbolSizeColumns = version.getSymbolSizeColumns();
     
     // TODO(bbrown): Make this work with rectangular codes
-    if (bitMatrix.getDimension() != symbolSizeRows) {
+    if (bitMatrix.getHeight() != symbolSizeRows) {
       throw new IllegalArgumentException("Dimension of bitMarix must match the version size");
     }
     
diff --git a/core/src/com/google/zxing/oned/Code128Writer.java b/core/src/com/google/zxing/oned/Code128Writer.java
index 9f4734b..0c22626 100644
--- a/core/src/com/google/zxing/oned/Code128Writer.java
+++ b/core/src/com/google/zxing/oned/Code128Writer.java
@@ -19,7 +19,7 @@ package com.google.zxing.oned;
 import java.util.Hashtable;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 
 /**
  * This object renders a CODE128 code as a {@link BitMatrix}.
@@ -28,7 +28,7 @@ import com.google.zxing.common.ByteMatrix;
  */
 public final class Code128Writer extends UPCEANWriter {
 
-	  public ByteMatrix encode(String contents,
+	  public BitMatrix encode(String contents,
                             BarcodeFormat format,
                             int width,
                             int height,
diff --git a/core/src/com/google/zxing/oned/Code39Writer.java b/core/src/com/google/zxing/oned/Code39Writer.java
index 42ab1fd..fab63b2 100644
--- a/core/src/com/google/zxing/oned/Code39Writer.java
+++ b/core/src/com/google/zxing/oned/Code39Writer.java
@@ -19,7 +19,7 @@ package com.google.zxing.oned;
 import java.util.Hashtable;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 
 /**
  * This object renders a CODE39 code as a {@link BitMatrix}.
@@ -28,7 +28,7 @@ import com.google.zxing.common.ByteMatrix;
  */
 public final class Code39Writer extends UPCEANWriter {
 
-	  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height,
+	  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
 	      Hashtable hints) throws WriterException {
 	    if (format != BarcodeFormat.CODE_39) {
 	      throw new IllegalArgumentException("Can only encode CODE_39, but got " + format);
diff --git a/core/src/com/google/zxing/oned/EAN13Writer.java b/core/src/com/google/zxing/oned/EAN13Writer.java
index ff9371d..ca6d67a 100644
--- a/core/src/com/google/zxing/oned/EAN13Writer.java
+++ b/core/src/com/google/zxing/oned/EAN13Writer.java
@@ -18,14 +18,13 @@ package com.google.zxing.oned;
 
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 
 import java.util.Hashtable;
 
 
 /**
- * This object renders an EAN13 code as a ByteMatrix 2D array of greyscale
- * values.
+ * This object renders an EAN13 code as a {@link BitMatrix}.
  *
  * @author aripollak at gmail.com (Ari Pollak)
  */
@@ -37,7 +36,7 @@ public final class EAN13Writer extends UPCEANWriter {
       (7 * 6) + // right bars
       3; // end guard
 
-  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height,
+  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
       Hashtable hints) throws WriterException {
     if (format != BarcodeFormat.EAN_13) {
       throw new IllegalArgumentException("Can only encode EAN_13, but got " + format);
diff --git a/core/src/com/google/zxing/oned/EAN8Writer.java b/core/src/com/google/zxing/oned/EAN8Writer.java
index b665f5f..4273707 100644
--- a/core/src/com/google/zxing/oned/EAN8Writer.java
+++ b/core/src/com/google/zxing/oned/EAN8Writer.java
@@ -18,13 +18,12 @@ package com.google.zxing.oned;
 
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 
 import java.util.Hashtable;
 
 /**
- * This object renders an EAN8 code as a ByteMatrix 2D array of greyscale
- * values.
+ * This object renders an EAN8 code as a {@link BitMatrix}.
  *
  * @author aripollak at gmail.com (Ari Pollak)
  */
@@ -36,7 +35,7 @@ public final class EAN8Writer extends UPCEANWriter {
       (7 * 4) + // right bars
       3; // end guard
 
-  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height,
+  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
       Hashtable hints) throws WriterException {
     if (format != BarcodeFormat.EAN_8) {
       throw new IllegalArgumentException("Can only encode EAN_8, but got "
diff --git a/core/src/com/google/zxing/oned/ITFWriter.java b/core/src/com/google/zxing/oned/ITFWriter.java
index 1847f7b..b85a652 100644
--- a/core/src/com/google/zxing/oned/ITFWriter.java
+++ b/core/src/com/google/zxing/oned/ITFWriter.java
@@ -19,7 +19,7 @@ package com.google.zxing.oned;
 import java.util.Hashtable;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 
 /**
  * This object renders a ITF code as a {@link BitMatrix}.
@@ -28,7 +28,7 @@ import com.google.zxing.common.ByteMatrix;
  */
 public final class ITFWriter extends UPCEANWriter {
 
-	  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height,
+	  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
 	      Hashtable hints) throws WriterException {
 	    if (format != BarcodeFormat.ITF) {
 	      throw new IllegalArgumentException("Can only encode ITF, but got " + format);
diff --git a/core/src/com/google/zxing/oned/UPCEANWriter.java b/core/src/com/google/zxing/oned/UPCEANWriter.java
index b65c207..68fa4a0 100644
--- a/core/src/com/google/zxing/oned/UPCEANWriter.java
+++ b/core/src/com/google/zxing/oned/UPCEANWriter.java
@@ -19,7 +19,7 @@ package com.google.zxing.oned;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.Writer;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 
 import java.util.Hashtable;
 
@@ -31,12 +31,12 @@ import java.util.Hashtable;
  */
 public abstract class UPCEANWriter implements Writer {
 
-  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height)
+  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
   throws WriterException {
     return encode(contents, format, width, height, null);
   }
 
-  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height,
+  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
       Hashtable hints) throws WriterException {
     if (contents == null || contents.length() == 0) {
       throw new IllegalArgumentException("Found empty contents");
@@ -52,7 +52,7 @@ public abstract class UPCEANWriter implements Writer {
   }
 
   /** @return a byte array of horizontal pixels (0 = white, 1 = black) */
-  private static ByteMatrix renderResult(byte[] code, int width, int height) {
+  private static BitMatrix renderResult(byte[] code, int width, int height) {
     int inputWidth = code.length;
     // Add quiet zone on both sides
     int fullWidth = inputWidth + (UPCEANReader.START_END_PATTERN.length << 1);
@@ -62,37 +62,12 @@ public abstract class UPCEANWriter implements Writer {
     int multiple = outputWidth / fullWidth;
     int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
 
-    ByteMatrix output = new ByteMatrix(outputWidth, outputHeight);
-    byte[][] outputArray = output.getArray();
-
-    byte[] row = new byte[outputWidth];
-
-    // a. Write the white pixels at the left of each row
-    for (int x = 0; x < leftPadding; x++) {
-      row[x] = (byte) 255;
-    }
-
-    // b. Write the contents of this row of the barcode
-    int offset = leftPadding;
-    for (int x = 0; x < inputWidth; x++) {
-      byte value = (code[x] == 1) ? 0 : (byte) 255;
-      for (int z = 0; z < multiple; z++) {
-        row[offset + z] = value;
+    BitMatrix output = new BitMatrix(outputWidth, outputHeight);
+    for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
+      if (code[inputX] == 1) {
+        output.setRegion(outputX, 0, multiple, outputHeight);
       }
-      offset += multiple;
     }
-
-    // c. Write the white pixels at the right of each row
-    offset = leftPadding + (inputWidth * multiple);
-    for (int x = offset; x < outputWidth; x++) {
-      row[x] = (byte) 255;
-    }
-
-    // d. Write the completed row multiple times
-    for (int z = 0; z < outputHeight; z++) {
-      System.arraycopy(row, 0, outputArray[z], 0, outputWidth);
-    }
-
     return output;
   }
 
diff --git a/core/src/com/google/zxing/pdf417/decoder/BitMatrixParser.java b/core/src/com/google/zxing/pdf417/decoder/BitMatrixParser.java
index 7821483..29c0ba3 100644
--- a/core/src/com/google/zxing/pdf417/decoder/BitMatrixParser.java
+++ b/core/src/com/google/zxing/pdf417/decoder/BitMatrixParser.java
@@ -60,7 +60,7 @@ final class BitMatrixParser {
    * @return an array of codewords.
    */
   int[] readCodewords() throws FormatException {
-    int width = bitMatrix.getDimension();
+    int width = bitMatrix.getWidth();
     // TODO should be a rectangular matrix
     int height = width;
 
@@ -186,7 +186,7 @@ final class BitMatrixParser {
    */
   int processRow(int[] rowCounters, int rowNumber, int rowHeight, int[] codewords, int next)
       throws FormatException {
-    int width = bitMatrix.getDimension();
+    int width = bitMatrix.getWidth();
     int columnNumber = 0;
     long symbol = 0;
     for (int i = 0; i < width; i += MODULES_IN_SYMBOL) {
diff --git a/core/src/com/google/zxing/qrcode/QRCodeWriter.java b/core/src/com/google/zxing/qrcode/QRCodeWriter.java
index 7d516c6..c0a5e0a 100644
--- a/core/src/com/google/zxing/qrcode/QRCodeWriter.java
+++ b/core/src/com/google/zxing/qrcode/QRCodeWriter.java
@@ -20,7 +20,8 @@ import com.google.zxing.BarcodeFormat;
 import com.google.zxing.EncodeHintType;
 import com.google.zxing.Writer;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.encoder.ByteMatrix;
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 import com.google.zxing.qrcode.encoder.Encoder;
 import com.google.zxing.qrcode.encoder.QRCode;
@@ -28,7 +29,7 @@ import com.google.zxing.qrcode.encoder.QRCode;
 import java.util.Hashtable;
 
 /**
- * This object renders a QR Code as a ByteMatrix 2D array of greyscale values.
+ * This object renders a QR Code as a BitMatrix 2D array of greyscale values.
  *
  * @author dswitkin at google.com (Daniel Switkin)
  */
@@ -36,13 +37,13 @@ public final class QRCodeWriter implements Writer {
 
   private static final int QUIET_ZONE_SIZE = 4;
 
-  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height)
+  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
       throws WriterException {
 
     return encode(contents, format, width, height, null);
   }
 
-  public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height,
+  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
       Hashtable hints) throws WriterException {
 
     if (contents == null || contents.length() == 0) {
@@ -73,7 +74,7 @@ public final class QRCodeWriter implements Writer {
 
   // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses
   // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).
-  private static ByteMatrix renderResult(QRCode code, int width, int height) {
+  private static BitMatrix renderResult(QRCode code, int width, int height) {
     ByteMatrix input = code.getMatrix();
     int inputWidth = input.getWidth();
     int inputHeight = input.getHeight();
@@ -90,62 +91,18 @@ public final class QRCodeWriter implements Writer {
     int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
     int topPadding = (outputHeight - (inputHeight * multiple)) / 2;
 
-    ByteMatrix output = new ByteMatrix(outputWidth, outputHeight);
-    byte[][] outputArray = output.getArray();
+    BitMatrix output = new BitMatrix(outputWidth, outputHeight);
 
-    // We could be tricky and use the first row in each set of multiple as the temporary storage,
-    // instead of allocating this separate array.
-    byte[] row = new byte[outputWidth];
-
-    // 1. Write the white lines at the top
-    for (int y = 0; y < topPadding; y++) {
-      setRowColor(outputArray[y], (byte) 255);
-    }
-
-    // 2. Expand the QR image to the multiple
-    byte[][] inputArray = input.getArray();
-    for (int y = 0; y < inputHeight; y++) {
-      // a. Write the white pixels at the left of each row
-      for (int x = 0; x < leftPadding; x++) {
-        row[x] = (byte) 255;
-      }
-
-      // b. Write the contents of this row of the barcode
-      int offset = leftPadding;
-      for (int x = 0; x < inputWidth; x++) {
-        byte value = (inputArray[y][x] == 1) ? 0 : (byte) 255;
-        for (int z = 0; z < multiple; z++) {
-          row[offset + z] = value;
+    for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
+      // Write the contents of this row of the barcode
+      for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
+        if (input.get(inputX, inputY) == 1) {
+          output.setRegion(outputX, outputY, multiple, multiple);
         }
-        offset += multiple;
-      }
-
-      // c. Write the white pixels at the right of each row
-      offset = leftPadding + (inputWidth * multiple);
-      for (int x = offset; x < outputWidth; x++) {
-        row[x] = (byte) 255;
       }
-
-      // d. Write the completed row multiple times
-      offset = topPadding + (y * multiple);
-      for (int z = 0; z < multiple; z++) {
-        System.arraycopy(row, 0, outputArray[offset + z], 0, outputWidth);
-      }
-    }
-
-    // 3. Write the white lines at the bottom
-    int offset = topPadding + (inputHeight * multiple);
-    for (int y = offset; y < outputHeight; y++) {
-      setRowColor(outputArray[y], (byte) 255);
     }
 
     return output;
   }
 
-  private static void setRowColor(byte[] row, byte value) {
-    for (int x = 0; x < row.length; x++) {
-      row[x] = value;
-    }
-  }
-
 }
diff --git a/core/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java b/core/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java
index 2a820ec..d8eaad9 100644
--- a/core/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java
+++ b/core/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java
@@ -33,7 +33,7 @@ final class BitMatrixParser {
    * @throws FormatException if dimension is not >= 21 and 1 mod 4
    */
   BitMatrixParser(BitMatrix bitMatrix) throws FormatException {
-    int dimension = bitMatrix.getDimension();
+    int dimension = bitMatrix.getHeight();
     if (dimension < 21 || (dimension & 0x03) != 1) {
       throw FormatException.getFormatInstance();
     }
@@ -68,7 +68,7 @@ final class BitMatrixParser {
     }
 
     // Read the top-right/bottom-left pattern too
-    int dimension = bitMatrix.getDimension();
+    int dimension = bitMatrix.getHeight();
     int formatInfoBits2 = 0;
     int iMin = dimension - 8;
     for (int i = dimension - 1; i >= iMin; i--) {
@@ -98,7 +98,7 @@ final class BitMatrixParser {
       return parsedVersion;
     }
 
-    int dimension = bitMatrix.getDimension();
+    int dimension = bitMatrix.getHeight();
 
     int provisionalVersion = (dimension - 17) >> 2;
     if (provisionalVersion <= 6) {
@@ -154,7 +154,7 @@ final class BitMatrixParser {
     // Get the data mask for the format used in this QR Code. This will exclude
     // some bits from reading as we wind through the bit matrix.
     DataMask dataMask = DataMask.forReference((int) formatInfo.getDataMask());
-    int dimension = bitMatrix.getDimension();
+    int dimension = bitMatrix.getHeight();
     dataMask.unmaskBitMatrix(bitMatrix, dimension);
 
     BitMatrix functionPattern = version.buildFunctionPattern();
diff --git a/core/src/com/google/zxing/qrcode/encoder/BitVector.java b/core/src/com/google/zxing/qrcode/encoder/BitVector.java
deleted file mode 100644
index a78078b..0000000
--- a/core/src/com/google/zxing/qrcode/encoder/BitVector.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.encoder;
-
-/**
- * JAVAPORT: This should be combined with BitArray in the future, although that class is not yet
- * dynamically resizeable. This implementation is reasonable but there is a lot of function calling
- * in loops I'd like to get rid of.
- *
- * @author satorux at google.com (Satoru Takabayashi) - creator
- * @author dswitkin at google.com (Daniel Switkin) - ported from C++
- */
-public final class BitVector {
-
-  private int sizeInBits;
-  private byte[] array;
-
-  // For efficiency, start out with some room to work.
-  private static final int DEFAULT_SIZE_IN_BYTES = 32;
-
-  public BitVector() {
-    sizeInBits = 0;
-    array = new byte[DEFAULT_SIZE_IN_BYTES];
-  }
-
-  // Return the bit value at "index".
-  public int at(int index) {
-    if (index < 0 || index >= sizeInBits) {
-      throw new IllegalArgumentException("Bad index: " + index);
-    }
-    int value = array[index >> 3] & 0xff;
-    return (value >> (7 - (index & 0x7))) & 1;
-  }
-
-  // Return the number of bits in the bit vector.
-  public int size() {
-    return sizeInBits;
-  }
-
-  // Return the number of bytes in the bit vector.
-  public int sizeInBytes() {
-    return (sizeInBits + 7) >> 3;
-  }
-
-  // Append one bit to the bit vector.
-  public void appendBit(int bit) {
-    if (!(bit == 0 || bit == 1)) {
-      throw new IllegalArgumentException("Bad bit");
-    }
-    int numBitsInLastByte = sizeInBits & 0x7;
-    // We'll expand array if we don't have bits in the last byte.
-    if (numBitsInLastByte == 0) {
-      appendByte(0);
-      sizeInBits -= 8;
-    }
-    // Modify the last byte.
-    array[sizeInBits >> 3] |= (bit << (7 - numBitsInLastByte));
-    ++sizeInBits;
-  }
-
-  // Append "numBits" bits in "value" to the bit vector.
-  // REQUIRES: 0<= numBits <= 32.
-  //
-  // Examples:
-  // - appendBits(0x00, 1) adds 0.
-  // - appendBits(0x00, 4) adds 0000.
-  // - appendBits(0xff, 8) adds 11111111.
-  public void appendBits(int value, int numBits) {
-    if (numBits < 0 || numBits > 32) {
-      throw new IllegalArgumentException("Num bits must be between 0 and 32");
-    }
-    int numBitsLeft = numBits;
-    while (numBitsLeft > 0) {
-      // Optimization for byte-oriented appending.
-      if ((sizeInBits & 0x7) == 0 && numBitsLeft >= 8) {
-        int newByte = (value >> (numBitsLeft - 8)) & 0xff;
-        appendByte(newByte);
-        numBitsLeft -= 8;
-      } else {
-        int bit = (value >> (numBitsLeft - 1)) & 1;
-        appendBit(bit);
-        --numBitsLeft;
-      }
-    }
-  }
-
-  // Append "bits".
-  public void appendBitVector(BitVector bits) {
-    int size = bits.size();
-    for (int i = 0; i < size; ++i) {
-      appendBit(bits.at(i));
-    }
-  }
-
-  // Modify the bit vector by XOR'ing with "other"
-  public void xor(BitVector other) {
-    if (sizeInBits != other.size()) {
-      throw new IllegalArgumentException("BitVector sizes don't match");
-    }
-    int sizeInBytes = (sizeInBits + 7) >> 3;
-    for (int i = 0; i < sizeInBytes; ++i) {
-      // The last byte could be incomplete (i.e. not have 8 bits in
-      // it) but there is no problem since 0 XOR 0 == 0.
-      array[i] ^= other.array[i];
-    }
-  }
-
-  // Return String like "01110111" for debugging.
-  public String toString() {
-    StringBuffer result = new StringBuffer(sizeInBits);
-    for (int i = 0; i < sizeInBits; ++i) {
-      if (at(i) == 0) {
-        result.append('0');
-      } else if (at(i) == 1) {
-        result.append('1');
-      } else {
-        throw new IllegalArgumentException("Byte isn't 0 or 1");
-      }
-    }
-    return result.toString();
-  }
-
-  // Callers should not assume that array.length is the exact number of bytes needed to hold
-  // sizeInBits - it will typically be larger for efficiency.
-  public byte[] getArray() {
-    return array;
-  }
-
-  // Add a new byte to the end, possibly reallocating and doubling the size of the array if we've
-  // run out of room.
-  private void appendByte(int value) {
-    if ((sizeInBits >> 3) == array.length) {
-      byte[] newArray = new byte[(array.length << 1)];
-      System.arraycopy(array, 0, newArray, 0, array.length);
-      array = newArray;
-    }
-    array[sizeInBits >> 3] = (byte) value;
-    sizeInBits += 8;
-  }
-
-}
diff --git a/core/src/com/google/zxing/qrcode/encoder/BlockPair.java b/core/src/com/google/zxing/qrcode/encoder/BlockPair.java
index fece499..5714d9c 100644
--- a/core/src/com/google/zxing/qrcode/encoder/BlockPair.java
+++ b/core/src/com/google/zxing/qrcode/encoder/BlockPair.java
@@ -16,23 +16,21 @@
 
 package com.google.zxing.qrcode.encoder;
 
-import com.google.zxing.common.ByteArray;
-
 final class BlockPair {
 
-  private final ByteArray dataBytes;
-  private final ByteArray errorCorrectionBytes;
+  private final byte[] dataBytes;
+  private final byte[] errorCorrectionBytes;
 
-  BlockPair(ByteArray data, ByteArray errorCorrection) {
+  BlockPair(byte[] data, byte[] errorCorrection) {
     dataBytes = data;
     errorCorrectionBytes = errorCorrection;
   }
 
-  public ByteArray getDataBytes() {
+  public byte[] getDataBytes() {
     return dataBytes;
   }
 
-  public ByteArray getErrorCorrectionBytes() {
+  public byte[] getErrorCorrectionBytes() {
     return errorCorrectionBytes;
   }
 
diff --git a/core/src/com/google/zxing/common/ByteMatrix.java b/core/src/com/google/zxing/qrcode/encoder/ByteMatrix.java
similarity index 94%
rename from core/src/com/google/zxing/common/ByteMatrix.java
rename to core/src/com/google/zxing/qrcode/encoder/ByteMatrix.java
index 9ac01bc..eb248a2 100644
--- a/core/src/com/google/zxing/common/ByteMatrix.java
+++ b/core/src/com/google/zxing/qrcode/encoder/ByteMatrix.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.google.zxing.common;
+package com.google.zxing.qrcode.encoder;
 
 /**
  * A class which wraps a 2D array of bytes. The default usage is signed. If you want to use it as a
@@ -61,6 +61,10 @@ public final class ByteMatrix {
     bytes[y][x] = (byte) value;
   }
 
+  public void set(int x, int y, boolean value) {
+    bytes[y][x] = (byte) (value ? 1 : 0);
+  }
+
   public void clear(byte value) {
     for (int y = 0; y < height; ++y) {
       for (int x = 0; x < width; ++x) {
diff --git a/core/src/com/google/zxing/qrcode/encoder/Encoder.java b/core/src/com/google/zxing/qrcode/encoder/Encoder.java
index fd02c3b..2217b36 100644
--- a/core/src/com/google/zxing/qrcode/encoder/Encoder.java
+++ b/core/src/com/google/zxing/qrcode/encoder/Encoder.java
@@ -18,8 +18,7 @@ package com.google.zxing.qrcode.encoder;
 
 import com.google.zxing.EncodeHintType;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteArray;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitArray;
 import com.google.zxing.common.CharacterSetECI;
 import com.google.zxing.common.reedsolomon.GF256;
 import com.google.zxing.common.reedsolomon.ReedSolomonEncoder;
@@ -91,14 +90,14 @@ public final class Encoder {
     Mode mode = chooseMode(content, encoding);
 
     // Step 2: Append "bytes" into "dataBits" in appropriate encoding.
-    BitVector dataBits = new BitVector();
+    BitArray dataBits = new BitArray();
     appendBytes(content, mode, dataBits, encoding);
     // Step 3: Initialize QR code that can contain "dataBits".
-    int numInputBytes = dataBits.sizeInBytes();
+    int numInputBytes = dataBits.getSizeInBytes();
     initQRCode(numInputBytes, ecLevel, mode, qrCode);
 
     // Step 4: Build another bit vector that contains header and data.
-    BitVector headerAndDataBits = new BitVector();
+    BitArray headerAndDataBits = new BitArray();
 
     // Step 4.5: Append ECI message if applicable
     if (mode == Mode.BYTE && !DEFAULT_BYTE_MODE_ENCODING.equals(encoding)) {
@@ -110,15 +109,15 @@ public final class Encoder {
 
     appendModeInfo(mode, headerAndDataBits);
 
-    int numLetters = mode.equals(Mode.BYTE) ? dataBits.sizeInBytes() : content.length();
+    int numLetters = mode.equals(Mode.BYTE) ? dataBits.getSizeInBytes() : content.length();
     appendLengthInfo(numLetters, qrCode.getVersion(), mode, headerAndDataBits);
-    headerAndDataBits.appendBitVector(dataBits);
+    headerAndDataBits.appendBitArray(dataBits);
 
     // Step 5: Terminate the bits properly.
     terminateBits(qrCode.getNumDataBytes(), headerAndDataBits);
 
     // Step 6: Interleave data bits with error correction code.
-    BitVector finalBits = new BitVector();
+    BitArray finalBits = new BitArray();
     interleaveWithECBytes(headerAndDataBits, qrCode.getNumTotalBytes(), qrCode.getNumDataBytes(),
         qrCode.getNumRSBlocks(), finalBits);
 
@@ -201,7 +200,7 @@ public final class Encoder {
     return true;
   }
 
-  private static int chooseMaskPattern(BitVector bits, ErrorCorrectionLevel ecLevel, int version,
+  private static int chooseMaskPattern(BitArray bits, ErrorCorrectionLevel ecLevel, int version,
       ByteMatrix matrix) throws WriterException {
 
     int minPenalty = Integer.MAX_VALUE;  // Lower penalty is better.
@@ -261,41 +260,29 @@ public final class Encoder {
   /**
    * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).
    */
-  static void terminateBits(int numDataBytes, BitVector bits) throws WriterException {
+  static void terminateBits(int numDataBytes, BitArray bits) throws WriterException {
     int capacity = numDataBytes << 3;
-    if (bits.size() > capacity) {
-      throw new WriterException("data bits cannot fit in the QR Code" + bits.size() + " > " +
+    if (bits.getSize() > capacity) {
+      throw new WriterException("data bits cannot fit in the QR Code" + bits.getSize() + " > " +
           capacity);
     }
-    // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.
-    // TODO: srowen says we can remove this for loop, since the 4 terminator bits are optional if
-    // the last byte has less than 4 bits left. So it amounts to padding the last byte with zeroes
-    // either way.
-    for (int i = 0; i < 4 && bits.size() < capacity; ++i) {
-      bits.appendBit(0);
+    for (int i = 0; i < 4 && bits.getSize() < capacity; ++i) {
+      bits.appendBit(false);
     }
-    int numBitsInLastByte = bits.size() % 8;
+    // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.
     // If the last byte isn't 8-bit aligned, we'll add padding bits.
+    int numBitsInLastByte = bits.getSize() & 0x07;    
     if (numBitsInLastByte > 0) {
-      int numPaddingBits = 8 - numBitsInLastByte;
-      for (int i = 0; i < numPaddingBits; ++i) {
-        bits.appendBit(0);
+      for (int i = numBitsInLastByte; i < 8; i++) {
+        bits.appendBit(false);
       }
     }
-    // Should be 8-bit aligned here.
-    if (bits.size() % 8 != 0) {
-      throw new WriterException("Number of bits is not a multiple of 8");
-    }
     // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).
-    int numPaddingBytes = numDataBytes - bits.sizeInBytes();
+    int numPaddingBytes = numDataBytes - bits.getSizeInBytes();
     for (int i = 0; i < numPaddingBytes; ++i) {
-      if (i % 2 == 0) {
-        bits.appendBits(0xec, 8);
-      } else {
-        bits.appendBits(0x11, 8);
-      }
+      bits.appendBits(((i & 0x01) == 0) ? 0xEC : 0x11, 8);
     }
-    if (bits.size() != capacity) {
+    if (bits.getSize() != capacity) {
       throw new WriterException("Bits size does not equal capacity");
     }
   }
@@ -358,11 +345,11 @@ public final class Encoder {
    * Interleave "bits" with corresponding error correction bytes. On success, store the result in
    * "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.
    */
-  static void interleaveWithECBytes(BitVector bits, int numTotalBytes,
-      int numDataBytes, int numRSBlocks, BitVector result) throws WriterException {
+  static void interleaveWithECBytes(BitArray bits, int numTotalBytes,
+      int numDataBytes, int numRSBlocks, BitArray result) throws WriterException {
 
     // "bits" must have "getNumDataBytes" bytes of data.
-    if (bits.sizeInBytes() != numDataBytes) {
+    if (bits.getSizeInBytes() != numDataBytes) {
       throw new WriterException("Number of bits and data bytes does not match");
     }
 
@@ -382,13 +369,14 @@ public final class Encoder {
           numTotalBytes, numDataBytes, numRSBlocks, i,
           numDataBytesInBlock, numEcBytesInBlock);
 
-      ByteArray dataBytes = new ByteArray();
-      dataBytes.set(bits.getArray(), dataBytesOffset, numDataBytesInBlock[0]);
-      ByteArray ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]);
+      int size = numDataBytesInBlock[0];
+      byte[] dataBytes = new byte[size];
+      bits.toBytes(8*dataBytesOffset, dataBytes, 0, size);
+      byte[] ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]);
       blocks.addElement(new BlockPair(dataBytes, ecBytes));
 
-      maxNumDataBytes = Math.max(maxNumDataBytes, dataBytes.size());
-      maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.size());
+      maxNumDataBytes = Math.max(maxNumDataBytes, size);
+      maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length);
       dataBytesOffset += numDataBytesInBlock[0];
     }
     if (numDataBytes != dataBytesOffset) {
@@ -398,38 +386,38 @@ public final class Encoder {
     // First, place data blocks.
     for (int i = 0; i < maxNumDataBytes; ++i) {
       for (int j = 0; j < blocks.size(); ++j) {
-        ByteArray dataBytes = ((BlockPair) blocks.elementAt(j)).getDataBytes();
-        if (i < dataBytes.size()) {
-          result.appendBits(dataBytes.at(i), 8);
+        byte[] dataBytes = ((BlockPair) blocks.elementAt(j)).getDataBytes();
+        if (i < dataBytes.length) {
+          result.appendBits(dataBytes[i], 8);
         }
       }
     }
     // Then, place error correction blocks.
     for (int i = 0; i < maxNumEcBytes; ++i) {
       for (int j = 0; j < blocks.size(); ++j) {
-        ByteArray ecBytes = ((BlockPair) blocks.elementAt(j)).getErrorCorrectionBytes();
-        if (i < ecBytes.size()) {
-          result.appendBits(ecBytes.at(i), 8);
+        byte[] ecBytes = ((BlockPair) blocks.elementAt(j)).getErrorCorrectionBytes();
+        if (i < ecBytes.length) {
+          result.appendBits(ecBytes[i], 8);
         }
       }
     }
-    if (numTotalBytes != result.sizeInBytes()) {  // Should be same.
+    if (numTotalBytes != result.getSizeInBytes()) {  // Should be same.
       throw new WriterException("Interleaving error: " + numTotalBytes + " and " +
-          result.sizeInBytes() + " differ.");
+          result.getSizeInBytes() + " differ.");
     }
   }
 
-  static ByteArray generateECBytes(ByteArray dataBytes, int numEcBytesInBlock) {
-    int numDataBytes = dataBytes.size();
+  static byte[] generateECBytes(byte[] dataBytes, int numEcBytesInBlock) {
+    int numDataBytes = dataBytes.length;
     int[] toEncode = new int[numDataBytes + numEcBytesInBlock];
     for (int i = 0; i < numDataBytes; i++) {
-      toEncode[i] = dataBytes.at(i);
+      toEncode[i] = dataBytes[i] & 0xFF;
     }
     new ReedSolomonEncoder(GF256.QR_CODE_FIELD).encode(toEncode, numEcBytesInBlock);
 
-    ByteArray ecBytes = new ByteArray(numEcBytesInBlock);
+    byte[] ecBytes = new byte[numEcBytesInBlock];
     for (int i = 0; i < numEcBytesInBlock; i++) {
-      ecBytes.set(i, toEncode[numDataBytes + i]);
+      ecBytes[i] = (byte) toEncode[numDataBytes + i];
     }
     return ecBytes;
   }
@@ -437,7 +425,7 @@ public final class Encoder {
   /**
    * Append mode info. On success, store the result in "bits".
    */
-  static void appendModeInfo(Mode mode, BitVector bits) {
+  static void appendModeInfo(Mode mode, BitArray bits) {
     bits.appendBits(mode.getBits(), 4);
   }
 
@@ -445,7 +433,7 @@ public final class Encoder {
   /**
    * Append length info. On success, store the result in "bits".
    */
-  static void appendLengthInfo(int numLetters, int version, Mode mode, BitVector bits)
+  static void appendLengthInfo(int numLetters, int version, Mode mode, BitArray bits)
       throws WriterException {
     int numBits = mode.getCharacterCountBits(Version.getVersionForNumber(version));
     if (numLetters > ((1 << numBits) - 1)) {
@@ -457,7 +445,7 @@ public final class Encoder {
   /**
    * Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits".
    */
-  static void appendBytes(String content, Mode mode, BitVector bits, String encoding)
+  static void appendBytes(String content, Mode mode, BitArray bits, String encoding)
       throws WriterException {
     if (mode.equals(Mode.NUMERIC)) {
       appendNumericBytes(content, bits);
@@ -472,7 +460,7 @@ public final class Encoder {
     }
   }
 
-  static void appendNumericBytes(String content, BitVector bits) {
+  static void appendNumericBytes(String content, BitArray bits) {
     int length = content.length();
     int i = 0;
     while (i < length) {
@@ -496,7 +484,7 @@ public final class Encoder {
     }
   }
 
-  static void appendAlphanumericBytes(String content, BitVector bits) throws WriterException {
+  static void appendAlphanumericBytes(String content, BitArray bits) throws WriterException {
     int length = content.length();
     int i = 0;
     while (i < length) {
@@ -520,7 +508,7 @@ public final class Encoder {
     }
   }
 
-  static void append8BitBytes(String content, BitVector bits, String encoding)
+  static void append8BitBytes(String content, BitArray bits, String encoding)
       throws WriterException {
     byte[] bytes;
     try {
@@ -533,7 +521,7 @@ public final class Encoder {
     }
   }
 
-  static void appendKanjiBytes(String content, BitVector bits) throws WriterException {
+  static void appendKanjiBytes(String content, BitArray bits) throws WriterException {
     byte[] bytes;
     try {
       bytes = content.getBytes("Shift_JIS");
@@ -559,7 +547,7 @@ public final class Encoder {
     }
   }
 
-  private static void appendECI(CharacterSetECI eci, BitVector bits) {
+  private static void appendECI(CharacterSetECI eci, BitArray bits) {
     bits.appendBits(Mode.ECI.getBits(), 4);
     // This is correct for values up to 127, which is all we need now.
     bits.appendBits(eci.getValue(), 8);
diff --git a/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java b/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java
index e4806e5..c7f3c48 100644
--- a/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java
+++ b/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java
@@ -16,8 +16,6 @@
 
 package com.google.zxing.qrcode.encoder;
 
-import com.google.zxing.common.ByteMatrix;
-
 /**
  * @author satorux at google.com (Satoru Takabayashi) - creator
  * @author dswitkin at google.com (Daniel Switkin) - ported from C++
diff --git a/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java b/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java
index c4c007f..542159e 100644
--- a/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java
+++ b/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java
@@ -17,7 +17,7 @@
 package com.google.zxing.qrcode.encoder;
 
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitArray;
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 
 /**
@@ -136,7 +136,7 @@ public final class MatrixUtil {
 
   // Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On
   // success, store the result in "matrix" and return true.
-  public static void buildMatrix(BitVector dataBits, ErrorCorrectionLevel ecLevel, int version,
+  public static void buildMatrix(BitArray dataBits, ErrorCorrectionLevel ecLevel, int version,
       int maskPattern, ByteMatrix matrix) throws WriterException {
     clearMatrix(matrix);
     embedBasicPatterns(version, matrix);
@@ -169,13 +169,13 @@ public final class MatrixUtil {
   // Embed type information. On success, modify the matrix.
   public static void embedTypeInfo(ErrorCorrectionLevel ecLevel, int maskPattern, ByteMatrix matrix)
       throws WriterException {
-    BitVector typeInfoBits = new BitVector();
+    BitArray typeInfoBits = new BitArray();
     makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);
 
-    for (int i = 0; i < typeInfoBits.size(); ++i) {
+    for (int i = 0; i < typeInfoBits.getSize(); ++i) {
       // Place bits in LSB to MSB order.  LSB (least significant bit) is the last value in
       // "typeInfoBits".
-      int bit = typeInfoBits.at(typeInfoBits.size() - 1 - i);
+      boolean bit = typeInfoBits.get(typeInfoBits.getSize() - 1 - i);
 
       // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).
       int x1 = TYPE_INFO_COORDINATES[i][0];
@@ -202,14 +202,14 @@ public final class MatrixUtil {
     if (version < 7) {  // Version info is necessary if version >= 7.
       return;  // Don't need version info.
     }
-    BitVector versionInfoBits = new BitVector();
+    BitArray versionInfoBits = new BitArray();
     makeVersionInfoBits(version, versionInfoBits);
 
     int bitIndex = 6 * 3 - 1;  // It will decrease from 17 to 0.
     for (int i = 0; i < 6; ++i) {
       for (int j = 0; j < 3; ++j) {
         // Place bits in LSB (least significant bit) to MSB order.
-        int bit = versionInfoBits.at(bitIndex);
+        boolean bit = versionInfoBits.get(bitIndex);
         bitIndex--;
         // Left bottom corner.
         matrix.set(i, matrix.getHeight() - 11 + j, bit);
@@ -222,7 +222,7 @@ public final class MatrixUtil {
   // Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true.
   // For debugging purposes, it skips masking process if "getMaskPattern" is -1.
   // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.
-  public static void embedDataBits(BitVector dataBits, int maskPattern, ByteMatrix matrix)
+  public static void embedDataBits(BitArray dataBits, int maskPattern, ByteMatrix matrix)
       throws WriterException {
     int bitIndex = 0;
     int direction = -1;
@@ -241,20 +241,20 @@ public final class MatrixUtil {
           if (!isEmpty(matrix.get(xx, y))) {
             continue;
           }
-          int bit;
-          if (bitIndex < dataBits.size()) {
-            bit = dataBits.at(bitIndex);
+          boolean bit;
+          if (bitIndex < dataBits.getSize()) {
+            bit = dataBits.get(bitIndex);
             ++bitIndex;
           } else {
             // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described
             // in 8.4.9 of JISX0510:2004 (p. 24).
-            bit = 0;
+            bit = false;
           }
 
           // Skip masking if mask_pattern is -1.
           if (maskPattern != -1) {
             if (MaskUtil.getDataMaskBit(maskPattern, xx, y)) {
-              bit ^= 0x1;
+              bit = !bit;
             }
           }
           matrix.set(xx, y, bit);
@@ -266,8 +266,8 @@ public final class MatrixUtil {
       x -= 2;  // Move to the left.
     }
     // All bits should be consumed.
-    if (bitIndex != dataBits.size()) {
-      throw new WriterException("Not all bits consumed: " + bitIndex + '/' + dataBits.size());
+    if (bitIndex != dataBits.getSize()) {
+      throw new WriterException("Not all bits consumed: " + bitIndex + '/' + dataBits.getSize());
     }
   }
 
@@ -326,7 +326,7 @@ public final class MatrixUtil {
   // Make bit vector of type information. On success, store the result in "bits" and return true.
   // Encode error correction level and mask pattern. See 8.9 of
   // JISX0510:2004 (p.45) for details.
-  public static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitVector bits)
+  public static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitArray bits)
       throws WriterException {
     if (!QRCode.isValidMaskPattern(maskPattern)) {
       throw new WriterException("Invalid mask pattern");
@@ -337,24 +337,24 @@ public final class MatrixUtil {
     int bchCode = calculateBCHCode(typeInfo, TYPE_INFO_POLY);
     bits.appendBits(bchCode, 10);
 
-    BitVector maskBits = new BitVector();
+    BitArray maskBits = new BitArray();
     maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15);
     bits.xor(maskBits);
 
-    if (bits.size() != 15) {  // Just in case.
-      throw new WriterException("should not happen but we got: " + bits.size());
+    if (bits.getSize() != 15) {  // Just in case.
+      throw new WriterException("should not happen but we got: " + bits.getSize());
     }
   }
 
   // Make bit vector of version information. On success, store the result in "bits" and return true.
   // See 8.10 of JISX0510:2004 (p.45) for details.
-  public static void makeVersionInfoBits(int version, BitVector bits) throws WriterException {
+  public static void makeVersionInfoBits(int version, BitArray bits) throws WriterException {
     bits.appendBits(version, 6);
     int bchCode = calculateBCHCode(version, VERSION_INFO_POLY);
     bits.appendBits(bchCode, 12);
 
-    if (bits.size() != 18) {  // Just in case.
-      throw new WriterException("should not happen but we got: " + bits.size());
+    if (bits.getSize() != 18) {  // Just in case.
+      throw new WriterException("should not happen but we got: " + bits.getSize());
     }
   }
 
diff --git a/core/src/com/google/zxing/qrcode/encoder/QRCode.java b/core/src/com/google/zxing/qrcode/encoder/QRCode.java
index 75ec9e7..05c8185 100644
--- a/core/src/com/google/zxing/qrcode/encoder/QRCode.java
+++ b/core/src/com/google/zxing/qrcode/encoder/QRCode.java
@@ -16,7 +16,6 @@
 
 package com.google.zxing.qrcode.encoder;
 
-import com.google.zxing.common.ByteMatrix;
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 import com.google.zxing.qrcode.decoder.Mode;
 
diff --git a/core/test/src/com/google/zxing/common/BitMatrixTestCase.java b/core/test/src/com/google/zxing/common/BitMatrixTestCase.java
index 91c8769..5f14066 100644
--- a/core/test/src/com/google/zxing/common/BitMatrixTestCase.java
+++ b/core/test/src/com/google/zxing/common/BitMatrixTestCase.java
@@ -26,7 +26,7 @@ public final class BitMatrixTestCase extends TestCase {
 
   public void testGetSet() {
     BitMatrix matrix = new BitMatrix(33);
-    assertEquals(33, matrix.getDimension());
+    assertEquals(33, matrix.getHeight());
     for (int y = 0; y < 33; y++) {
       for (int x = 0; x < 33; x++) {
         if (y * x % 3 == 0) {
@@ -94,7 +94,7 @@ public final class BitMatrixTestCase extends TestCase {
   public void testGetRow() {
     BitMatrix matrix = new BitMatrix(102, 5);
     for (int x = 0; x < 102; x++) {
-      if ((x & 3) == 0) {
+      if ((x & 0x03) == 0) {
         matrix.set(x, 2);
       }
     }
@@ -114,7 +114,7 @@ public final class BitMatrixTestCase extends TestCase {
     assertEquals(200, array3.getSize());
 
     for (int x = 0; x < 102; x++) {
-      boolean on = ((x & 3) == 0);
+      boolean on = ((x & 0x03) == 0);
       assertEquals(on, array.get(x));
       assertEquals(on, array2.get(x));
       assertEquals(on, array3.get(x));
diff --git a/core/test/src/com/google/zxing/oned/EAN13WriterTestCase.java b/core/test/src/com/google/zxing/oned/EAN13WriterTestCase.java
index 7887ee4..f95bad4 100644
--- a/core/test/src/com/google/zxing/oned/EAN13WriterTestCase.java
+++ b/core/test/src/com/google/zxing/oned/EAN13WriterTestCase.java
@@ -18,7 +18,7 @@ package com.google.zxing.oned;
 
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 import junit.framework.TestCase;
 
 /**
@@ -28,12 +28,9 @@ public final class EAN13WriterTestCase extends TestCase {
 
   public void testEncode() throws WriterException {
     String testStr = "00010100010110100111011001100100110111101001110101010110011011011001000010101110010011101000100101000";
-    ByteMatrix result = new EAN13Writer().encode("5901234123457", BarcodeFormat.EAN_13, testStr.length(), 0);
-    byte[] row = result.getArray()[0];
-
+    BitMatrix result = new EAN13Writer().encode("5901234123457", BarcodeFormat.EAN_13, testStr.length(), 0);
     for (int i = 0; i < testStr.length(); i++) {
-      assertEquals("Element " + i, (Integer.parseInt(testStr.substring(i,
-          i + 1)) == 1) ? 0 : (byte) 255, row[i]);
+      assertEquals("Element " + i,  testStr.charAt(i) == '1', result.get(i, 0));
     }
   }
 
diff --git a/core/test/src/com/google/zxing/oned/EAN8WriterTestCase.java b/core/test/src/com/google/zxing/oned/EAN8WriterTestCase.java
index 7c71694..6537583 100644
--- a/core/test/src/com/google/zxing/oned/EAN8WriterTestCase.java
+++ b/core/test/src/com/google/zxing/oned/EAN8WriterTestCase.java
@@ -18,7 +18,7 @@ package com.google.zxing.oned;
 
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 import junit.framework.TestCase;
 
 /**
@@ -28,18 +28,11 @@ public final class EAN8WriterTestCase extends TestCase {
 
   public void testEncode() throws WriterException {
     String testStr = "0001010001011010111101111010110111010101001110111001010001001011100101000";
-    ByteMatrix result = new EAN8Writer().encode("96385074", BarcodeFormat.EAN_8, testStr.length(), 0);
-    byte[] row = result.getArray()[0];
-    /*
-    for (int i = 0; i < row.length; i++) {
-      System.out.print(row[i] + 1);
-    }
-    System.out.println();
-    */
-
+    BitMatrix result = new EAN8Writer().encode("96385074", BarcodeFormat.EAN_8, testStr.length(), 0);
     for (int i = 0; i < testStr.length(); i++) {
-      assertEquals("Element " + i, (Integer.parseInt(testStr.substring(i,
-          i + 1)) == 1) ? 0 : (byte) 255, row[i]);
+      assertEquals("Element " + i,
+                   testStr.charAt(i) == '1',
+                   result.get(i, 0));
     }
   }
 
diff --git a/core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java b/core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java
index e9ef9b1..da9b17d 100644
--- a/core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java
+++ b/core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java
@@ -19,7 +19,7 @@ package com.google.zxing.qrcode;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.EncodeHintType;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitMatrix;
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 import junit.framework.TestCase;
 
@@ -53,20 +53,22 @@ public final class QRCodeWriterTestCase extends TestCase {
   }
 
   // In case the golden images are not monochromatic, convert the RGB values to greyscale.
-  private static ByteMatrix createMatrixFromImage(BufferedImage image) {
+  private static BitMatrix createMatrixFromImage(BufferedImage image) {
     int width = image.getWidth();
     int height = image.getHeight();
     int[] pixels = new int[width * height];
     image.getRGB(0, 0, width, height, pixels, 0, width);
 
-    ByteMatrix matrix = new ByteMatrix(width, height);
+    BitMatrix matrix = new BitMatrix(width, height);
     for (int y = 0; y < height; y++) {
       for (int x = 0; x < width; x++) {
         int pixel = pixels[y * width + x];
         int luminance = (306 * ((pixel >> 16) & 0xFF) +
             601 * ((pixel >> 8) & 0xFF) +
             117 * (pixel & 0xFF)) >> 10;
-        matrix.set(x, y, luminance);
+        if (luminance <= 0x7F) {
+          matrix.set(x, y);
+        }
       }
     }
     return matrix;
@@ -76,7 +78,7 @@ public final class QRCodeWriterTestCase extends TestCase {
     // The QR should be multiplied up to fit, with extra padding if necessary
     int bigEnough = 256;
     QRCodeWriter writer = new QRCodeWriter();
-    ByteMatrix matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, bigEnough,
+    BitMatrix matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, bigEnough,
         bigEnough, null);
     assertNotNull(matrix);
     assertEquals(bigEnough, matrix.getWidth());
@@ -105,21 +107,18 @@ public final class QRCodeWriterTestCase extends TestCase {
 
     BufferedImage image = loadImage(fileName);
     assertNotNull(image);
-    ByteMatrix goldenResult = createMatrixFromImage(image);
+    BitMatrix goldenResult = createMatrixFromImage(image);
     assertNotNull(goldenResult);
 
     QRCodeWriter writer = new QRCodeWriter();
     Hashtable<EncodeHintType,Object> hints = new Hashtable<EncodeHintType,Object>();
     hints.put(EncodeHintType.ERROR_CORRECTION, ecLevel);
-    ByteMatrix generatedResult = writer.encode(contents, BarcodeFormat.QR_CODE, resolution,
+    BitMatrix generatedResult = writer.encode(contents, BarcodeFormat.QR_CODE, resolution,
         resolution, hints);
 
-    assertEquals("Width should be " + resolution + ", but was " + generatedResult.getWidth(),
-        resolution, generatedResult.getWidth());
-    assertEquals("Height should be " + resolution + ", but was " + generatedResult.getHeight(),
-        resolution, generatedResult.getHeight());
-    assertTrue("Expected " + goldenResult.toString() + " but got " + generatedResult.toString(),
-        Arrays.deepEquals(goldenResult.getArray(), generatedResult.getArray()));
+    assertEquals(resolution, generatedResult.getWidth());
+    assertEquals(resolution, generatedResult.getHeight());
+    assertEquals(goldenResult, generatedResult);
   }
 
   // Golden images are generated with "qrcode_sample.cc". The images are checked with both eye balls
diff --git a/core/test/src/com/google/zxing/qrcode/encoder/BitVectorTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/BitVectorTestCase.java
index 05abfd6..87cc4ae 100644
--- a/core/test/src/com/google/zxing/qrcode/encoder/BitVectorTestCase.java
+++ b/core/test/src/com/google/zxing/qrcode/encoder/BitVectorTestCase.java
@@ -16,6 +16,7 @@
 
 package com.google.zxing.qrcode.encoder;
 
+import com.google.zxing.common.BitArray;
 import junit.framework.TestCase;
 
 /**
@@ -24,154 +25,154 @@ import junit.framework.TestCase;
  */
 public class BitVectorTestCase extends TestCase {
 
-  private static int getUnsignedByte(BitVector v, int index) {
-    return v.getArray()[index] & 0xff;
+  private static long getUnsignedInt(BitArray v, int index) {
+    long result = 0L;
+    for (int i = 0, offset = index << 3; i < 32; i++) {
+      if (v.get(offset + i)) {
+        result |= 1L << (31 - i);
+      }
+    }
+    return result;
   }
 
   public void testAppendBit() {
-    BitVector v = new BitVector();
-    assertEquals(0, v.sizeInBytes());
+    BitArray v = new BitArray();
+    assertEquals(0, v.getSizeInBytes());
     // 1
-    v.appendBit(1);
-    assertEquals(1, v.size());
-    assertEquals(0x80, getUnsignedByte(v, 0));
+    v.appendBit(true);
+    assertEquals(1, v.getSize());
+    assertEquals(0x80000000L, getUnsignedInt(v, 0));
     // 10
-    v.appendBit(0);
-    assertEquals(2, v.size());
-    assertEquals(0x80, getUnsignedByte(v, 0));
+    v.appendBit(false);
+    assertEquals(2, v.getSize());
+    assertEquals(0x80000000L, getUnsignedInt(v, 0));
     // 101
-    v.appendBit(1);
-    assertEquals(3, v.size());
-    assertEquals(0xa0, getUnsignedByte(v, 0));
+    v.appendBit(true);
+    assertEquals(3, v.getSize());
+    assertEquals(0xa0000000L, getUnsignedInt(v, 0));
     // 1010
-    v.appendBit(0);
-    assertEquals(4, v.size());
-    assertEquals(0xa0, getUnsignedByte(v, 0));
+    v.appendBit(false);
+    assertEquals(4, v.getSize());
+    assertEquals(0xa0000000L, getUnsignedInt(v, 0));
     // 10101
-    v.appendBit(1);
-    assertEquals(5, v.size());
-    assertEquals(0xa8, getUnsignedByte(v, 0));
+    v.appendBit(true);
+    assertEquals(5, v.getSize());
+    assertEquals(0xa8000000L, getUnsignedInt(v, 0));
     // 101010
-    v.appendBit(0);
-    assertEquals(6, v.size());
-    assertEquals(0xa8, getUnsignedByte(v, 0));
+    v.appendBit(false);
+    assertEquals(6, v.getSize());
+    assertEquals(0xa8000000L, getUnsignedInt(v, 0));
     // 1010101
-    v.appendBit(1);
-    assertEquals(7, v.size());
-    assertEquals(0xaa, getUnsignedByte(v, 0));
+    v.appendBit(true);
+    assertEquals(7, v.getSize());
+    assertEquals(0xaa000000L, getUnsignedInt(v, 0));
     // 10101010
-    v.appendBit(0);
-    assertEquals(8, v.size());
-    assertEquals(0xaa, getUnsignedByte(v, 0));
+    v.appendBit(false);
+    assertEquals(8, v.getSize());
+    assertEquals(0xaa000000L, getUnsignedInt(v, 0));
     // 10101010 1
-    v.appendBit(1);
-    assertEquals(9, v.size());
-    assertEquals(0xaa, getUnsignedByte(v, 0));
-    assertEquals(0x80, getUnsignedByte(v, 1));
+    v.appendBit(true);
+    assertEquals(9, v.getSize());
+    assertEquals(0xaa800000L, getUnsignedInt(v, 0));
     // 10101010 10
-    v.appendBit(0);
-    assertEquals(10, v.size());
-    assertEquals(0xaa, getUnsignedByte(v, 0));
-    assertEquals(0x80, getUnsignedByte(v, 1));
+    v.appendBit(false);
+    assertEquals(10, v.getSize());
+    assertEquals(0xaa800000L, getUnsignedInt(v, 0));
   }
 
   public void testAppendBits() {
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       v.appendBits(0x1, 1);
-      assertEquals(1, v.size());
-      assertEquals(0x80, getUnsignedByte(v, 0));
+      assertEquals(1, v.getSize());
+      assertEquals(0x80000000L, getUnsignedInt(v, 0));
     }
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       v.appendBits(0xff, 8);
-      assertEquals(8, v.size());
-      assertEquals(0xff, getUnsignedByte(v, 0));
+      assertEquals(8, v.getSize());
+      assertEquals(0xff000000L, getUnsignedInt(v, 0));
     }
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       v.appendBits(0xff7, 12);
-      assertEquals(12, v.size());
-      assertEquals(0xff, getUnsignedByte(v, 0));
-      assertEquals(0x70, getUnsignedByte(v, 1));
+      assertEquals(12, v.getSize());
+      assertEquals(0xff700000L, getUnsignedInt(v, 0));
     }
   }
 
   public void testNumBytes() {
-    BitVector v = new BitVector();
-    assertEquals(0, v.sizeInBytes());
-    v.appendBit(0);
+    BitArray v = new BitArray();
+    assertEquals(0, v.getSizeInBytes());
+    v.appendBit(false);
     // 1 bit was added in the vector, so 1 byte should be consumed.
-    assertEquals(1, v.sizeInBytes());
+    assertEquals(1, v.getSizeInBytes());
     v.appendBits(0, 7);
-    assertEquals(1, v.sizeInBytes());
+    assertEquals(1, v.getSizeInBytes());
     v.appendBits(0, 8);
-    assertEquals(2, v.sizeInBytes());
+    assertEquals(2, v.getSizeInBytes());
     v.appendBits(0, 1);
     // We now have 17 bits, so 3 bytes should be consumed.
-    assertEquals(3, v.sizeInBytes());
+    assertEquals(3, v.getSizeInBytes());
   }
 
   public void testAppendBitVector() {
-    BitVector v1 = new BitVector();
+    BitArray v1 = new BitArray();
     v1.appendBits(0xbe, 8);
-    BitVector v2 = new BitVector();
+    BitArray v2 = new BitArray();
     v2.appendBits(0xef, 8);
-    v1.appendBitVector(v2);
+    v1.appendBitArray(v2);
     // beef = 1011 1110 1110 1111
-    assertEquals("1011111011101111", v1.toString());
+    assertEquals(" X.XXXXX. XXX.XXXX", v1.toString());
   }
 
   public void testXOR() {
     {
-      BitVector v1 = new BitVector();
+      BitArray v1 = new BitArray();
       v1.appendBits(0x5555aaaa, 32);
-      BitVector v2 = new BitVector();
+      BitArray v2 = new BitArray();
       v2.appendBits(0xaaaa5555, 32);
       v1.xor(v2);
-      assertEquals(0xff, getUnsignedByte(v1, 0));
-      assertEquals(0xff, getUnsignedByte(v1, 1));
-      assertEquals(0xff, getUnsignedByte(v1, 2));
-      assertEquals(0xff, getUnsignedByte(v1, 3));
+      assertEquals(0xffffffffL, getUnsignedInt(v1, 0));
     }
     {
-      BitVector v1 = new BitVector();
+      BitArray v1 = new BitArray();
       v1.appendBits(0x2a, 7);  // 010 1010
-      BitVector v2 = new BitVector();
+      BitArray v2 = new BitArray();
       v2.appendBits(0x55, 7);  // 101 0101
       v1.xor(v2);
-      assertEquals(0xfe, getUnsignedByte(v1, 0));  // 1111 1110
+      assertEquals(0xfe000000L, getUnsignedInt(v1, 0));  // 1111 1110
     }
   }
 
   public void testAt() {
-    BitVector v = new BitVector();
+    BitArray v = new BitArray();
     v.appendBits(0xdead, 16);  // 1101 1110 1010 1101
-    assertEquals(1, v.at(0));
-    assertEquals(1, v.at(1));
-    assertEquals(0, v.at(2));
-    assertEquals(1, v.at(3));
+    assertTrue(v.get(0));
+    assertTrue(v.get(1));
+    assertFalse(v.get(2));
+    assertTrue(v.get(3));
 
-    assertEquals(1, v.at(4));
-    assertEquals(1, v.at(5));
-    assertEquals(1, v.at(6));
-    assertEquals(0, v.at(7));
+    assertTrue(v.get(4));
+    assertTrue(v.get(5));
+    assertTrue(v.get(6));
+    assertFalse(v.get(7));
 
-    assertEquals(1, v.at(8));
-    assertEquals(0, v.at(9));
-    assertEquals(1, v.at(10));
-    assertEquals(0, v.at(11));
+    assertTrue(v.get(8));
+    assertFalse(v.get(9));
+    assertTrue(v.get(10));
+    assertFalse(v.get(11));
 
-    assertEquals(1, v.at(12));
-    assertEquals(1, v.at(13));
-    assertEquals(0, v.at(14));
-    assertEquals(1, v.at(15));
+    assertTrue(v.get(12));
+    assertTrue(v.get(13));
+    assertFalse(v.get(14));
+    assertTrue(v.get(15));
   }
 
   public void testToString() {
-    BitVector v = new BitVector();
+    BitArray v = new BitArray();
     v.appendBits(0xdead, 16);  // 1101 1110 1010 1101
-    assertEquals("1101111010101101", v.toString());
+    assertEquals(" XX.XXXX. X.X.XX.X", v.toString());
   }
 
 }
diff --git a/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java
index 86e6200..89912fa 100644
--- a/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java
+++ b/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java
@@ -17,7 +17,7 @@
 package com.google.zxing.qrcode.encoder;
 
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteArray;
+import com.google.zxing.common.BitArray;
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 import com.google.zxing.qrcode.decoder.Mode;
 import junit.framework.TestCase;
@@ -60,28 +60,29 @@ public final class EncoderTestCase extends TestCase {
 
   public void testChooseMode() throws WriterException {
     // Numeric mode.
-    assertEquals(Mode.NUMERIC, Encoder.chooseMode("0"));
-    assertEquals(Mode.NUMERIC, Encoder.chooseMode("0123456789"));
+    assertSame(Mode.NUMERIC, Encoder.chooseMode("0"));
+    assertSame(Mode.NUMERIC, Encoder.chooseMode("0123456789"));
     // Alphanumeric mode.
-    assertEquals(Mode.ALPHANUMERIC, Encoder.chooseMode("A"));
-    assertEquals(Mode.ALPHANUMERIC,
-        Encoder.chooseMode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"));
+    assertSame(Mode.ALPHANUMERIC, Encoder.chooseMode("A"));
+    assertSame(Mode.ALPHANUMERIC,
+               Encoder.chooseMode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"));
     // 8-bit byte mode.
-    assertEquals(Mode.BYTE, Encoder.chooseMode("a"));
-    assertEquals(Mode.BYTE, Encoder.chooseMode("#"));
-    assertEquals(Mode.BYTE, Encoder.chooseMode(""));
+    assertSame(Mode.BYTE, Encoder.chooseMode("a"));
+    assertSame(Mode.BYTE, Encoder.chooseMode("#"));
+    assertSame(Mode.BYTE, Encoder.chooseMode(""));
     // Kanji mode.  We used to use MODE_KANJI for these, but we stopped
     // doing that as we cannot distinguish Shift_JIS from other encodings
     // from data bytes alone.  See also comments in qrcode_encoder.h.
 
     // AIUE in Hiragana in Shift_JIS
-    assertEquals(Mode.BYTE, Encoder.chooseMode(shiftJISString(new byte[] {0x8,0xa,0x8,0xa,0x8,0xa,0x8,(byte)0xa6})));
+    assertSame(Mode.BYTE,
+               Encoder.chooseMode(shiftJISString(new byte[]{0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, (byte) 0xa6})));
 
     // Nihon in Kanji in Shift_JIS.
-    assertEquals(Mode.BYTE, Encoder.chooseMode(shiftJISString(new byte[] {0x9,0xf,0x9,0x7b})));
+    assertSame(Mode.BYTE, Encoder.chooseMode(shiftJISString(new byte[]{0x9, 0xf, 0x9, 0x7b})));
 
     // Sou-Utsu-Byou in Kanji in Shift_JIS.
-    assertEquals(Mode.BYTE, Encoder.chooseMode(shiftJISString(new byte[] {0xe,0x4,0x9,0x5,0x9,0x61})));
+    assertSame(Mode.BYTE, Encoder.chooseMode(shiftJISString(new byte[]{0xe, 0x4, 0x9, 0x5, 0x9, 0x61})));
   }
 
   public void testEncode() throws WriterException {
@@ -126,43 +127,43 @@ public final class EncoderTestCase extends TestCase {
   }
 
   public void testAppendModeInfo() {
-    BitVector bits = new BitVector();
+    BitArray bits = new BitArray();
     Encoder.appendModeInfo(Mode.NUMERIC, bits);
-    assertEquals("0001", bits.toString());
+    assertEquals(" ...X", bits.toString());
   }
 
   public void testAppendLengthInfo() throws WriterException {
     {
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendLengthInfo(1,  // 1 letter (1/1).
 						  1,  // version 1.
 						  Mode.NUMERIC,
 						  bits);
-      assertEquals("0000000001", bits.toString());  // 10 bits.
+      assertEquals(" ........ .X", bits.toString());  // 10 bits.
     }
     {
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendLengthInfo(2,  // 2 letters (2/1).
 						  10,  // version 10.
 						  Mode.ALPHANUMERIC,
 						  bits);
-      assertEquals("00000000010", bits.toString());  // 11 bits.
+      assertEquals(" ........ .X.", bits.toString());  // 11 bits.
     }
     {
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendLengthInfo(255,  // 255 letter (255/1).
 						  27,  // version 27.
 						  Mode.BYTE,
 						  bits);
-      assertEquals("0000000011111111", bits.toString());  // 16 bits.
+      assertEquals(" ........ XXXXXXXX", bits.toString());  // 16 bits.
     }
     {
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendLengthInfo(512,  // 512 letters (1024/2).
 						  40,  // version 40.
 						  Mode.KANJI,
 						  bits);
-      assertEquals("001000000000", bits.toString());  // 12 bits.
+      assertEquals(" ..X..... ....", bits.toString());  // 12 bits.
     }
   }
 
@@ -170,16 +171,16 @@ public final class EncoderTestCase extends TestCase {
     {
       // Should use appendNumericBytes.
       // 1 = 01 = 0001 in 4 bits.
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendBytes("1", Mode.NUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
-      assertEquals("0001" , bits.toString());
+      assertEquals(" ...X" , bits.toString());
     }
     {
       // Should use appendAlphanumericBytes.
       // A = 10 = 0xa = 001010 in 6 bits
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendBytes("A", Mode.ALPHANUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
-      assertEquals("001010" , bits.toString());
+      assertEquals(" ..X.X." , bits.toString());
       // Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
       try {
         Encoder.appendBytes("a", Mode.ALPHANUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
@@ -190,60 +191,60 @@ public final class EncoderTestCase extends TestCase {
     {
       // Should use append8BitBytes.
       // 0x61, 0x62, 0x63
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendBytes("abc", Mode.BYTE, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
-      assertEquals("011000010110001001100011", bits.toString());
+      assertEquals(" .XX....X .XX...X. .XX...XX", bits.toString());
       // Anything can be encoded in QRCode.MODE_8BIT_BYTE.
       Encoder.appendBytes("\0", Mode.BYTE, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
     }
     {
       // Should use appendKanjiBytes.
       // 0x93, 0x5f
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendBytes(shiftJISString(new byte[] {(byte)0x93,0x5f}), Mode.KANJI, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
-      assertEquals("0110110011111", bits.toString());
+      assertEquals(" .XX.XX.. XXXXX", bits.toString());
     }
   }
 
   public void testTerminateBits() throws WriterException {
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       Encoder.terminateBits(0, v);
       assertEquals("", v.toString());
     }
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       Encoder.terminateBits(1, v);
-      assertEquals("00000000", v.toString());
+      assertEquals(" ........", v.toString());
     }
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       v.appendBits(0, 3);  // Append 000
       Encoder.terminateBits(1, v);
-      assertEquals("00000000", v.toString());
+      assertEquals(" ........", v.toString());
     }
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       v.appendBits(0, 5);  // Append 00000
       Encoder.terminateBits(1, v);
-      assertEquals("00000000", v.toString());
+      assertEquals(" ........", v.toString());
     }
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       v.appendBits(0, 8);  // Append 00000000
       Encoder.terminateBits(1, v);
-      assertEquals("00000000", v.toString());
+      assertEquals(" ........", v.toString());
     }
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       Encoder.terminateBits(2, v);
-      assertEquals("0000000011101100", v.toString());
+      assertEquals(" ........ XXX.XX..", v.toString());
     }
     {
-      BitVector v = new BitVector();
+      BitArray v = new BitArray();
       v.appendBits(0, 1);  // Append 0
       Encoder.terminateBits(3, v);
-      assertEquals("000000001110110000010001", v.toString());
+      assertEquals(" ........ XXX.XX.. ...X...X", v.toString());
     }
   }
 
@@ -286,11 +287,11 @@ public final class EncoderTestCase extends TestCase {
   public void testInterleaveWithECBytes() throws WriterException {
     {
       byte[] dataBytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236};
-      BitVector in = new BitVector();
+      BitArray in = new BitArray();
       for (byte dataByte: dataBytes) {
         in.appendBits(dataByte, 8);
       }
-      BitVector out = new BitVector();
+      BitArray out = new BitArray();
       Encoder.interleaveWithECBytes(in, 26, 9, 1, out);
       byte[] expected = {
           // Data bytes.
@@ -299,8 +300,9 @@ public final class EncoderTestCase extends TestCase {
           42, (byte)159, 74, (byte)221, (byte)244, (byte)169, (byte)239, (byte)150, (byte)138, 70,
           (byte)237, 85, (byte)224, 96, 74, (byte)219, 61,
       };
-      assertEquals(expected.length, out.sizeInBytes());
-      byte[] outArray = out.getArray();
+      assertEquals(expected.length, out.getSizeInBytes());
+      byte[] outArray = new byte[expected.length];
+      out.toBytes(0, outArray, 0, expected.length);
       // Can't use Arrays.equals(), because outArray may be longer than out.sizeInBytes()
       for (int x = 0; x < expected.length; x++) {
         assertEquals(expected[x], outArray[x]);
@@ -316,11 +318,11 @@ public final class EncoderTestCase extends TestCase {
           (byte)135, (byte)151, (byte)160, (byte)236, 17, (byte)236, 17, (byte)236, 17, (byte)236,
           17
       };
-      BitVector in = new BitVector();
+      BitArray in = new BitArray();
       for (byte dataByte: dataBytes) {
         in.appendBits(dataByte, 8);
       }
-      BitVector out = new BitVector();
+      BitArray out = new BitArray();
       Encoder.interleaveWithECBytes(in, 134, 62, 4, out);
       byte[] expected = {
           // Data bytes.
@@ -339,8 +341,9 @@ public final class EncoderTestCase extends TestCase {
           (byte)140, 61, (byte)179, (byte)154, (byte)214, (byte)138, (byte)147, 87, 27, 96, 77, 47,
           (byte)187, 49, (byte)156, (byte)214,
       };
-      assertEquals(expected.length, out.sizeInBytes());
-      byte[] outArray = out.getArray();
+      assertEquals(expected.length, out.getSizeInBytes());
+      byte[] outArray = new byte[expected.length];
+      out.toBytes(0, outArray, 0, expected.length);
       for (int x = 0; x < expected.length; x++) {
         assertEquals(expected[x], outArray[x]);
       }
@@ -350,31 +353,31 @@ public final class EncoderTestCase extends TestCase {
   public void testAppendNumericBytes() {
     {
       // 1 = 01 = 0001 in 4 bits.
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendNumericBytes("1", bits);
-      assertEquals("0001" , bits.toString());
+      assertEquals(" ...X" , bits.toString());
     }
     {
       // 12 = 0xc = 0001100 in 7 bits.
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendNumericBytes("12", bits);
-      assertEquals("0001100" , bits.toString());
+      assertEquals(" ...XX.." , bits.toString());
     }
     {
       // 123 = 0x7b = 0001111011 in 10 bits.
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendNumericBytes("123", bits);
-      assertEquals("0001111011" , bits.toString());
+      assertEquals(" ...XXXX. XX" , bits.toString());
     }
     {
       // 1234 = "123" + "4" = 0001111011 + 0100
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendNumericBytes("1234", bits);
-      assertEquals("0001111011" + "0100" , bits.toString());
+      assertEquals(" ...XXXX. XX.X.." , bits.toString());
     }
     {
       // Empty.
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendNumericBytes("", bits);
       assertEquals("" , bits.toString());
     }
@@ -383,31 +386,31 @@ public final class EncoderTestCase extends TestCase {
   public void testAppendAlphanumericBytes() throws WriterException {
     {
       // A = 10 = 0xa = 001010 in 6 bits
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendAlphanumericBytes("A", bits);
-      assertEquals("001010" , bits.toString());
+      assertEquals(" ..X.X." , bits.toString());
     }
     {
       // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendAlphanumericBytes("AB", bits);
-      assertEquals("00111001101", bits.toString());
+      assertEquals(" ..XXX..X X.X", bits.toString());
     }
     {
       // ABC = "AB" + "C" = 00111001101 + 001100
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendAlphanumericBytes("ABC", bits);
-      assertEquals("00111001101" + "001100" , bits.toString());
+      assertEquals(" ..XXX..X X.X..XX. ." , bits.toString());
     }
     {
       // Empty.
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.appendAlphanumericBytes("", bits);
       assertEquals("" , bits.toString());
     }
     {
       // Invalid data.
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       try {
         Encoder.appendAlphanumericBytes("abc", bits);
       } catch (WriterException we) {
@@ -419,13 +422,13 @@ public final class EncoderTestCase extends TestCase {
   public void testAppend8BitBytes() throws WriterException {
     {
       // 0x61, 0x62, 0x63
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.append8BitBytes("abc", bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
-      assertEquals("01100001" + "01100010" + "01100011", bits.toString());
+      assertEquals(" .XX....X .XX...X. .XX...XX", bits.toString());
     }
     {
       // Empty.
-      BitVector bits = new BitVector();
+      BitArray bits = new BitArray();
       Encoder.append8BitBytes("", bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
       assertEquals("", bits.toString());
     }
@@ -433,11 +436,11 @@ public final class EncoderTestCase extends TestCase {
 
   // Numbers are from page 21 of JISX0510:2004
   public void testAppendKanjiBytes() throws WriterException {
-      BitVector bits = new BitVector();
+    BitArray bits = new BitArray();
       Encoder.appendKanjiBytes(shiftJISString(new byte[] {(byte)0x93,0x5f}), bits);
-      assertEquals("0110110011111", bits.toString());
+      assertEquals(" .XX.XX.. XXXXX", bits.toString());
       Encoder.appendKanjiBytes(shiftJISString(new byte[] {(byte)0xe4,(byte)0xaa}), bits);
-      assertEquals("0110110011111" + "1101010101010", bits.toString());
+      assertEquals(" .XX.XX.. XXXXXXX. X.X.X.X. X.", bits.toString());
   }
 
   // Numbers are from http://www.swetake.com/qr/qr3.html and
@@ -445,37 +448,37 @@ public final class EncoderTestCase extends TestCase {
   public void testGenerateECBytes() {
     {
       byte[] dataBytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236};
-      ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 17);
+      byte[] ecBytes = Encoder.generateECBytes(dataBytes, 17);
       int[] expected = {
           42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61
       };
-      assertEquals(expected.length, ecBytes.size());
+      assertEquals(expected.length, ecBytes.length);
       for (int x = 0; x < expected.length; x++) {
-        assertEquals(expected[x], ecBytes.at(x));
+        assertEquals(expected[x], ecBytes[x] & 0xFF);
       }
     }
     {
       byte[] dataBytes = {67, 70, 22, 38, 54, 70, 86, 102, 118,
           (byte)134, (byte)150, (byte)166, (byte)182, (byte)198, (byte)214};
-      ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 18);
+      byte[] ecBytes = Encoder.generateECBytes(dataBytes, 18);
       int[] expected = {
           175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187
       };
-      assertEquals(expected.length, ecBytes.size());
+      assertEquals(expected.length, ecBytes.length);
       for (int x = 0; x < expected.length; x++) {
-        assertEquals(expected[x], ecBytes.at(x));
+        assertEquals(expected[x], ecBytes[x] & 0xFF);
       }
     }
     {
-      // High-order zero cofficient case.
+      // High-order zero coefficient case.
       byte[] dataBytes = {32, 49, (byte)205, 69, 42, 20, 0, (byte)236, 17};
-      ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 17);
+      byte[] ecBytes = Encoder.generateECBytes(dataBytes, 17);
       int[] expected = {
           0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213
       };
-      assertEquals(expected.length, ecBytes.size());
+      assertEquals(expected.length, ecBytes.length);
       for (int x = 0; x < expected.length; x++) {
-        assertEquals(expected[x], ecBytes.at(x));
+        assertEquals(expected[x], ecBytes[x] & 0xFF);
       }
     }
   }
diff --git a/core/test/src/com/google/zxing/qrcode/encoder/MaskUtilTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/MaskUtilTestCase.java
index 51790a8..183cdb1 100644
--- a/core/test/src/com/google/zxing/qrcode/encoder/MaskUtilTestCase.java
+++ b/core/test/src/com/google/zxing/qrcode/encoder/MaskUtilTestCase.java
@@ -16,7 +16,6 @@
 
 package com.google.zxing.qrcode.encoder;
 
-import com.google.zxing.common.ByteMatrix;
 import junit.framework.TestCase;
 
 /**
diff --git a/core/test/src/com/google/zxing/qrcode/encoder/MatrixUtilTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/MatrixUtilTestCase.java
index 12becfc..87336dc 100644
--- a/core/test/src/com/google/zxing/qrcode/encoder/MatrixUtilTestCase.java
+++ b/core/test/src/com/google/zxing/qrcode/encoder/MatrixUtilTestCase.java
@@ -17,7 +17,7 @@
 package com.google.zxing.qrcode.encoder;
 
 import com.google.zxing.WriterException;
-import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.BitArray;
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 import junit.framework.TestCase;
 
@@ -202,7 +202,7 @@ public final class MatrixUtilTestCase extends TestCase {
       " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
       " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
       " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
-    BitVector bits = new BitVector();
+    BitArray bits = new BitArray();
     ByteMatrix matrix = new ByteMatrix(21, 21);
     MatrixUtil.clearMatrix(matrix);
     MatrixUtil.embedBasicPatterns(1, matrix);
@@ -237,7 +237,7 @@ public final class MatrixUtilTestCase extends TestCase {
     char[] bytes = {32, 65, 205, 69, 41, 220, 46, 128, 236,
 		    42, 159, 74, 221, 244, 169, 239, 150, 138,
 		    70, 237, 85, 224, 96, 74, 219 , 61};
-    BitVector bits = new BitVector();
+    BitArray bits = new BitArray();
     for (char c: bytes) {
       bits.appendBits(c, 8);
     }
@@ -280,18 +280,18 @@ public final class MatrixUtilTestCase extends TestCase {
   // tested them in TEST(calculateBCHCode).
   public void testMakeVersionInfoBits() throws WriterException {
     // From Appendix D in JISX0510:2004 (p 68)
-    BitVector bits = new BitVector();
+    BitArray bits = new BitArray();
     MatrixUtil.makeVersionInfoBits(7, bits);
-    assertEquals("000111110010010100", bits.toString());
+    assertEquals(" ...XXXXX ..X..X.X ..", bits.toString());
   }
 
   // We don't test a lot of cases in this function since we've already
   // tested them in TEST(calculateBCHCode).
   public void testMakeTypeInfoInfoBits() throws WriterException {
     // From Appendix C in JISX0510:2004 (p 65)
-    BitVector bits = new BitVector();
+    BitArray bits = new BitArray();
     MatrixUtil.makeTypeInfoBits(ErrorCorrectionLevel.M,
 						   5, bits);
-    assertEquals("100000011001110", bits.toString());
+    assertEquals(" X......X X..XXX.", bits.toString());
   }
 }
diff --git a/core/test/src/com/google/zxing/qrcode/encoder/QRCodeTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/QRCodeTestCase.java
index e17cf80..3e25d76 100644
--- a/core/test/src/com/google/zxing/qrcode/encoder/QRCodeTestCase.java
+++ b/core/test/src/com/google/zxing/qrcode/encoder/QRCodeTestCase.java
@@ -16,7 +16,6 @@
 
 package com.google.zxing.qrcode.encoder;
 
-import com.google.zxing.common.ByteMatrix;
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 import com.google.zxing.qrcode.decoder.Mode;
 import junit.framework.TestCase;
diff --git a/javase/src/com/google/zxing/client/j2se/MatrixToImageWriter.java b/javase/src/com/google/zxing/client/j2se/MatrixToImageWriter.java
index 3c82a56..9184555 100644
--- a/javase/src/com/google/zxing/client/j2se/MatrixToImageWriter.java
+++ b/javase/src/com/google/zxing/client/j2se/MatrixToImageWriter.java
@@ -17,7 +17,6 @@
 package com.google.zxing.client.j2se;
 
 import com.google.zxing.common.BitMatrix;
-import com.google.zxing.common.ByteMatrix;
 
 import javax.imageio.ImageIO;
 import java.io.File;
@@ -26,7 +25,7 @@ import java.io.IOException;
 import java.awt.image.BufferedImage;
 
 /**
- * Writes a {@link BitMatrix} or {@link ByteMatrix} to {@link BufferedImage},
+ * Writes a {@link BitMatrix} to {@link BufferedImage},
  * file or stream. Provided here instead of core since it depends on
  * Java SE libraries.
  *
@@ -56,25 +55,6 @@ public final class MatrixToImageWriter {
   }
 
   /**
-   * Renders a {@link ByteMatrix} as an image, as a
-   * {@link BufferedImage}. The byte values are construed as (unsigned)
-   * luminance values, in theory.
-   * However, anything but 0 will be rendered as white, and 0 will be
-   * rendered as black.
-   */
-  public static BufferedImage toBufferedImage(ByteMatrix matrix) {
-    int width = matrix.getWidth();
-    int height = matrix.getHeight();
-    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
-    for (int x = 0; x < width; x++) {
-      for (int y = 0; y < height; y++) {
-        image.setRGB(x, y, matrix.get(x, y) == 0 ? BLACK : WHITE);
-      }
-    }
-    return image;
-  }
-
-  /**
    * Writes a {@link BitMatrix} to a file.
    *
    * @see #toBufferedImage(BitMatrix)
@@ -86,17 +66,6 @@ public final class MatrixToImageWriter {
   }
 
   /**
-   * Writes a {@link ByteMatrix} to a file.
-   *
-   * @see #toBufferedImage(ByteMatrix)
-   */
-  public static void writeToFile(ByteMatrix matrix, String format, File file)
-          throws IOException {
-    BufferedImage image = toBufferedImage(matrix);
-    ImageIO.write(image, format, file);
-  }
-
-  /**
    * Writes a {@link BitMatrix} to a stream.
    *
    * @see #toBufferedImage(BitMatrix)
@@ -107,15 +76,4 @@ public final class MatrixToImageWriter {
     ImageIO.write(image, format, stream);
   }
 
-  /**
-   * Writes a {@link ByteMatrix} to a stream.
-   *
-   * @see #toBufferedImage(ByteMatrix)
-   */
-  public static void writeToStream(ByteMatrix matrix, String format, OutputStream stream)
-          throws IOException {
-    BufferedImage image = toBufferedImage(matrix);
-    ImageIO.write(image, format, stream);
-  }
-
 }

-- 
Multi-format 1D/2D barcode image processing library



More information about the Pkg-google-commits mailing list