...

Source file src/golang.org/x/image/vp8l/transform.go

Documentation: golang.org/x/image/vp8l

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package vp8l
     6  
     7  // This file deals with image transforms, specified in section 3.
     8  
     9  // nTiles returns the number of tiles needed to cover size pixels, where each
    10  // tile's side is 1<<bits pixels long.
    11  func nTiles(size int32, bits uint32) int32 {
    12  	return (size + 1<<bits - 1) >> bits
    13  }
    14  
    15  const (
    16  	transformTypePredictor     = 0
    17  	transformTypeCrossColor    = 1
    18  	transformTypeSubtractGreen = 2
    19  	transformTypeColorIndexing = 3
    20  	nTransformTypes            = 4
    21  )
    22  
    23  // transform holds the parameters for an invertible transform.
    24  type transform struct {
    25  	// transformType is the type of the transform.
    26  	transformType uint32
    27  	// oldWidth is the width of the image before transformation (or
    28  	// equivalently, after inverse transformation). The color-indexing
    29  	// transform can reduce the width. For example, a 50-pixel-wide
    30  	// image that only needs 4 bits (half a byte) per color index can
    31  	// be transformed into a 25-pixel-wide image.
    32  	oldWidth int32
    33  	// bits is the log-2 size of the transform's tiles, for the predictor
    34  	// and cross-color transforms. 8>>bits is the number of bits per
    35  	// color index, for the color-index transform.
    36  	bits uint32
    37  	// pix is the tile values, for the predictor and cross-color
    38  	// transforms, and the color palette, for the color-index transform.
    39  	pix []byte
    40  }
    41  
    42  var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{
    43  	transformTypePredictor:     inversePredictor,
    44  	transformTypeCrossColor:    inverseCrossColor,
    45  	transformTypeSubtractGreen: inverseSubtractGreen,
    46  	transformTypeColorIndexing: inverseColorIndexing,
    47  }
    48  
    49  func inversePredictor(t *transform, pix []byte, h int32) []byte {
    50  	if t.oldWidth == 0 || h == 0 {
    51  		return pix
    52  	}
    53  	// The first pixel's predictor is mode 0 (opaque black).
    54  	pix[3] += 0xff
    55  	p, mask := int32(4), int32(1)<<t.bits-1
    56  	for x := int32(1); x < t.oldWidth; x++ {
    57  		// The rest of the first row's predictor is mode 1 (L).
    58  		pix[p+0] += pix[p-4]
    59  		pix[p+1] += pix[p-3]
    60  		pix[p+2] += pix[p-2]
    61  		pix[p+3] += pix[p-1]
    62  		p += 4
    63  	}
    64  	top, tilesPerRow := 0, nTiles(t.oldWidth, t.bits)
    65  	for y := int32(1); y < h; y++ {
    66  		// The first column's predictor is mode 2 (T).
    67  		pix[p+0] += pix[top+0]
    68  		pix[p+1] += pix[top+1]
    69  		pix[p+2] += pix[top+2]
    70  		pix[p+3] += pix[top+3]
    71  		p, top = p+4, top+4
    72  
    73  		q := 4 * (y >> t.bits) * tilesPerRow
    74  		predictorMode := t.pix[q+1] & 0x0f
    75  		q += 4
    76  		for x := int32(1); x < t.oldWidth; x++ {
    77  			if x&mask == 0 {
    78  				predictorMode = t.pix[q+1] & 0x0f
    79  				q += 4
    80  			}
    81  			switch predictorMode {
    82  			case 0: // Opaque black.
    83  				pix[p+3] += 0xff
    84  
    85  			case 1: // L.
    86  				pix[p+0] += pix[p-4]
    87  				pix[p+1] += pix[p-3]
    88  				pix[p+2] += pix[p-2]
    89  				pix[p+3] += pix[p-1]
    90  
    91  			case 2: // T.
    92  				pix[p+0] += pix[top+0]
    93  				pix[p+1] += pix[top+1]
    94  				pix[p+2] += pix[top+2]
    95  				pix[p+3] += pix[top+3]
    96  
    97  			case 3: // TR.
    98  				pix[p+0] += pix[top+4]
    99  				pix[p+1] += pix[top+5]
   100  				pix[p+2] += pix[top+6]
   101  				pix[p+3] += pix[top+7]
   102  
   103  			case 4: // TL.
   104  				pix[p+0] += pix[top-4]
   105  				pix[p+1] += pix[top-3]
   106  				pix[p+2] += pix[top-2]
   107  				pix[p+3] += pix[top-1]
   108  
   109  			case 5: // Average2(Average2(L, TR), T).
   110  				pix[p+0] += avg2(avg2(pix[p-4], pix[top+4]), pix[top+0])
   111  				pix[p+1] += avg2(avg2(pix[p-3], pix[top+5]), pix[top+1])
   112  				pix[p+2] += avg2(avg2(pix[p-2], pix[top+6]), pix[top+2])
   113  				pix[p+3] += avg2(avg2(pix[p-1], pix[top+7]), pix[top+3])
   114  
   115  			case 6: // Average2(L, TL).
   116  				pix[p+0] += avg2(pix[p-4], pix[top-4])
   117  				pix[p+1] += avg2(pix[p-3], pix[top-3])
   118  				pix[p+2] += avg2(pix[p-2], pix[top-2])
   119  				pix[p+3] += avg2(pix[p-1], pix[top-1])
   120  
   121  			case 7: // Average2(L, T).
   122  				pix[p+0] += avg2(pix[p-4], pix[top+0])
   123  				pix[p+1] += avg2(pix[p-3], pix[top+1])
   124  				pix[p+2] += avg2(pix[p-2], pix[top+2])
   125  				pix[p+3] += avg2(pix[p-1], pix[top+3])
   126  
   127  			case 8: // Average2(TL, T).
   128  				pix[p+0] += avg2(pix[top-4], pix[top+0])
   129  				pix[p+1] += avg2(pix[top-3], pix[top+1])
   130  				pix[p+2] += avg2(pix[top-2], pix[top+2])
   131  				pix[p+3] += avg2(pix[top-1], pix[top+3])
   132  
   133  			case 9: // Average2(T, TR).
   134  				pix[p+0] += avg2(pix[top+0], pix[top+4])
   135  				pix[p+1] += avg2(pix[top+1], pix[top+5])
   136  				pix[p+2] += avg2(pix[top+2], pix[top+6])
   137  				pix[p+3] += avg2(pix[top+3], pix[top+7])
   138  
   139  			case 10: // Average2(Average2(L, TL), Average2(T, TR)).
   140  				pix[p+0] += avg2(avg2(pix[p-4], pix[top-4]), avg2(pix[top+0], pix[top+4]))
   141  				pix[p+1] += avg2(avg2(pix[p-3], pix[top-3]), avg2(pix[top+1], pix[top+5]))
   142  				pix[p+2] += avg2(avg2(pix[p-2], pix[top-2]), avg2(pix[top+2], pix[top+6]))
   143  				pix[p+3] += avg2(avg2(pix[p-1], pix[top-1]), avg2(pix[top+3], pix[top+7]))
   144  
   145  			case 11: // Select(L, T, TL).
   146  				l0 := int32(pix[p-4])
   147  				l1 := int32(pix[p-3])
   148  				l2 := int32(pix[p-2])
   149  				l3 := int32(pix[p-1])
   150  				c0 := int32(pix[top-4])
   151  				c1 := int32(pix[top-3])
   152  				c2 := int32(pix[top-2])
   153  				c3 := int32(pix[top-1])
   154  				t0 := int32(pix[top+0])
   155  				t1 := int32(pix[top+1])
   156  				t2 := int32(pix[top+2])
   157  				t3 := int32(pix[top+3])
   158  				l := abs(c0-t0) + abs(c1-t1) + abs(c2-t2) + abs(c3-t3)
   159  				t := abs(c0-l0) + abs(c1-l1) + abs(c2-l2) + abs(c3-l3)
   160  				if l < t {
   161  					pix[p+0] += uint8(l0)
   162  					pix[p+1] += uint8(l1)
   163  					pix[p+2] += uint8(l2)
   164  					pix[p+3] += uint8(l3)
   165  				} else {
   166  					pix[p+0] += uint8(t0)
   167  					pix[p+1] += uint8(t1)
   168  					pix[p+2] += uint8(t2)
   169  					pix[p+3] += uint8(t3)
   170  				}
   171  
   172  			case 12: // ClampAddSubtractFull(L, T, TL).
   173  				pix[p+0] += clampAddSubtractFull(pix[p-4], pix[top+0], pix[top-4])
   174  				pix[p+1] += clampAddSubtractFull(pix[p-3], pix[top+1], pix[top-3])
   175  				pix[p+2] += clampAddSubtractFull(pix[p-2], pix[top+2], pix[top-2])
   176  				pix[p+3] += clampAddSubtractFull(pix[p-1], pix[top+3], pix[top-1])
   177  
   178  			case 13: // ClampAddSubtractHalf(Average2(L, T), TL).
   179  				pix[p+0] += clampAddSubtractHalf(avg2(pix[p-4], pix[top+0]), pix[top-4])
   180  				pix[p+1] += clampAddSubtractHalf(avg2(pix[p-3], pix[top+1]), pix[top-3])
   181  				pix[p+2] += clampAddSubtractHalf(avg2(pix[p-2], pix[top+2]), pix[top-2])
   182  				pix[p+3] += clampAddSubtractHalf(avg2(pix[p-1], pix[top+3]), pix[top-1])
   183  			}
   184  			p, top = p+4, top+4
   185  		}
   186  	}
   187  	return pix
   188  }
   189  
   190  func inverseCrossColor(t *transform, pix []byte, h int32) []byte {
   191  	var greenToRed, greenToBlue, redToBlue int32
   192  	p, mask, tilesPerRow := int32(0), int32(1)<<t.bits-1, nTiles(t.oldWidth, t.bits)
   193  	for y := int32(0); y < h; y++ {
   194  		q := 4 * (y >> t.bits) * tilesPerRow
   195  		for x := int32(0); x < t.oldWidth; x++ {
   196  			if x&mask == 0 {
   197  				redToBlue = int32(int8(t.pix[q+0]))
   198  				greenToBlue = int32(int8(t.pix[q+1]))
   199  				greenToRed = int32(int8(t.pix[q+2]))
   200  				q += 4
   201  			}
   202  			red := pix[p+0]
   203  			green := pix[p+1]
   204  			blue := pix[p+2]
   205  			red += uint8(uint32(greenToRed*int32(int8(green))) >> 5)
   206  			blue += uint8(uint32(greenToBlue*int32(int8(green))) >> 5)
   207  			blue += uint8(uint32(redToBlue*int32(int8(red))) >> 5)
   208  			pix[p+0] = red
   209  			pix[p+2] = blue
   210  			p += 4
   211  		}
   212  	}
   213  	return pix
   214  }
   215  
   216  func inverseSubtractGreen(t *transform, pix []byte, h int32) []byte {
   217  	for p := 0; p < len(pix); p += 4 {
   218  		green := pix[p+1]
   219  		pix[p+0] += green
   220  		pix[p+2] += green
   221  	}
   222  	return pix
   223  }
   224  
   225  func inverseColorIndexing(t *transform, pix []byte, h int32) []byte {
   226  	if t.bits == 0 {
   227  		for p := 0; p < len(pix); p += 4 {
   228  			i := 4 * uint32(pix[p+1])
   229  			pix[p+0] = t.pix[i+0]
   230  			pix[p+1] = t.pix[i+1]
   231  			pix[p+2] = t.pix[i+2]
   232  			pix[p+3] = t.pix[i+3]
   233  		}
   234  		return pix
   235  	}
   236  
   237  	vMask, xMask, bitsPerPixel := uint32(0), int32(0), uint32(8>>t.bits)
   238  	switch t.bits {
   239  	case 1:
   240  		vMask, xMask = 0x0f, 0x01
   241  	case 2:
   242  		vMask, xMask = 0x03, 0x03
   243  	case 3:
   244  		vMask, xMask = 0x01, 0x07
   245  	}
   246  
   247  	d, p, v, dst := 0, 0, uint32(0), make([]byte, 4*t.oldWidth*h)
   248  	for y := int32(0); y < h; y++ {
   249  		for x := int32(0); x < t.oldWidth; x++ {
   250  			if x&xMask == 0 {
   251  				v = uint32(pix[p+1])
   252  				p += 4
   253  			}
   254  
   255  			i := 4 * (v & vMask)
   256  			dst[d+0] = t.pix[i+0]
   257  			dst[d+1] = t.pix[i+1]
   258  			dst[d+2] = t.pix[i+2]
   259  			dst[d+3] = t.pix[i+3]
   260  			d += 4
   261  
   262  			v >>= bitsPerPixel
   263  		}
   264  	}
   265  	return dst
   266  }
   267  
   268  func abs(x int32) int32 {
   269  	if x < 0 {
   270  		return -x
   271  	}
   272  	return x
   273  }
   274  
   275  func avg2(a, b uint8) uint8 {
   276  	return uint8((int32(a) + int32(b)) / 2)
   277  }
   278  
   279  func clampAddSubtractFull(a, b, c uint8) uint8 {
   280  	x := int32(a) + int32(b) - int32(c)
   281  	if x < 0 {
   282  		return 0
   283  	}
   284  	if x > 255 {
   285  		return 255
   286  	}
   287  	return uint8(x)
   288  }
   289  
   290  func clampAddSubtractHalf(a, b uint8) uint8 {
   291  	x := int32(a) + (int32(a)-int32(b))/2
   292  	if x < 0 {
   293  		return 0
   294  	}
   295  	if x > 255 {
   296  		return 255
   297  	}
   298  	return uint8(x)
   299  }
   300  

View as plain text