Cracking Coding Interview - 5.8 Draw Line

Draw Line: A monochrome screen is stored as a single array of bytes, allowing eight consecutive pixels to be stored in one byte. The screen has width w, where w is divisible by 8 (that is, no byte will be split across rows). The height of the screen, of course, can be derived from the length of the array and the width. Implement a function that draws a horizontal line from (x1, y) to (x2, y).

The method signature should look something like:

1
drawline(byte[] screen, int width, int xl, int x2, int y)

Hints: #366, #381, #384, #391

解法

byte[] screen是一个一维数组,里面存放的是一个byte,byte中的1bit代表一个像素点。里面存的是:

1
2
|  byte  |  byte  |  byte  |  byte  |
[00100110,11100000,10100000,00001001, ...]

width是8的倍数,单位是bit,height = screen * / width。

所谓画一条线就是把这条线上的像素点代表的bit设为1。注意这道题目中的画的是水平线,不是斜线,所以比较简单。

先把byte [] screen变成下面这种形式看看:

1
2
3
4
5
6
7
8
9
|<-            width              ->|
 00000000 00000000 00000000 00000000
 00000000 00000000 00000000 00000000
         (x1, y)             (x2, y)
            v                   v
 00000000 00111111 11111111 11111000
 00000000 00000000 00000000 00000000
 00000000 00000000 00000000 00000000
 00000000 00000000 00000000 00000000

给定一个坐标让你求是第几个bit(从左往右数的,从0开始的):

1
int allBitIndex = (y - 1) * width + x

求位于第几个byte:

1
int byteIndex = allBitIndex / 8

求位于这个byte里的第几个bit:

1
int byteBitIndex = allBitIndex % 8

代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void drawline(byte[] screen, int width, int xl, int x2, int y) {
  Coord c1 = getCoord(width, x1, y);
  Coord c2 = getCoord(width, x2, y);
  byte allOne = (byte) (~0);

  // 把x1, x2(不含)之间字节的都设1
  for (int i = c1.byteIdx + 1; i < c2.byteIdx; i++) {
    screen[c1.byteIdx] = allOne;
  }
  if (c1.byteIdx != c2.byteIdx) { // 两个像素在同一个byte里
    // 把c1.bitIdx后面(含)都设1
    screen[c1.byteIdx] |= allOne >> c1.bitIdx;
    // 把c2.bitIdx前面(含)都设1
    screen[c2.byteIdx] |= allOne << (8 - c2.bitIdx - 1);    
  } else {
    screen[c1.byteIdx] |= (allOne >> c1.bitIdx) & (allOne << (8 - c2.bitIdx - 1));
  }
}

private Coord getCoord(int width, int x, int y) {
  int allBitIdx = (y - 1) * width + x;
  int byteIdx = allBitIdx / 8; // 也可以是 allBitIdx >> 3
  int bitIdx = allBitIdx % 8;  // 也可以是 allBitIdx & 7  ( 0..0 111)
  return new Coord(byteIdx, bitIdx);
}

版权

评论