summaryrefslogtreecommitdiff
path: root/libgo/go/image/internal/imageutil/impl.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/image/internal/imageutil/impl.go')
-rw-r--r--libgo/go/image/internal/imageutil/impl.go232
1 files changed, 152 insertions, 80 deletions
diff --git a/libgo/go/image/internal/imageutil/impl.go b/libgo/go/image/internal/imageutil/impl.go
index fd7826d4a9..3696b08e41 100644
--- a/libgo/go/image/internal/imageutil/impl.go
+++ b/libgo/go/image/internal/imageutil/impl.go
@@ -44,32 +44,50 @@ func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
- yy1 := int32(src.Y[yi]) * 0x10100 // Convert 0x12 to 0x121200.
+ yy1 := int32(src.Y[yi]) * 0x010100 // Convert 0x12 to 0x121200.
cb1 := int32(src.Cb[ci]) - 128
cr1 := int32(src.Cr[ci]) - 128
- r := (yy1 + 91881*cr1) >> 16
- g := (yy1 - 22554*cb1 - 46802*cr1) >> 16
- b := (yy1 + 116130*cb1) >> 16
- if r < 0 {
- r = 0
- } else if r > 255 {
- r = 255
+
+ // The bit twiddling below is equivalent to
+ //
+ // r := (yy1 + 91881*cr1) >> 16
+ // if r < 0 {
+ // r = 0
+ // } else if r > 0xff {
+ // r = ^int32(0)
+ // }
+ //
+ // but uses fewer branches and is faster.
+ // Note that the uint8 type conversion in the return
+ // statement will convert ^int32(0) to 0xff.
+ // The code below to compute g and b uses a similar pattern.
+ r := yy1 + 91881*cr1
+ if uint32(r)&0xff000000 == 0 {
+ r >>= 16
+ } else {
+ r = ^(r >> 31)
}
- if g < 0 {
- g = 0
- } else if g > 255 {
- g = 255
+
+ g := yy1 - 22554*cb1 - 46802*cr1
+ if uint32(g)&0xff000000 == 0 {
+ g >>= 16
+ } else {
+ g = ^(g >> 31)
}
- if b < 0 {
- b = 0
- } else if b > 255 {
- b = 255
+
+ b := yy1 + 116130*cb1
+ if uint32(b)&0xff000000 == 0 {
+ b >>= 16
+ } else {
+ b = ^(b >> 31)
}
- dpix[x+0] = uint8(r)
- dpix[x+1] = uint8(g)
- dpix[x+2] = uint8(b)
- dpix[x+3] = 255
+ // use a temp slice to hint to the compiler that a single bounds check suffices
+ rgba := dpix[x : x+4 : len(dpix)]
+ rgba[0] = uint8(r)
+ rgba[1] = uint8(g)
+ rgba[2] = uint8(b)
+ rgba[3] = 255
}
}
@@ -83,32 +101,50 @@ func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
ci := ciBase + sx/2
// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
- yy1 := int32(src.Y[yi]) * 0x10100 // Convert 0x12 to 0x121200.
+ yy1 := int32(src.Y[yi]) * 0x010100 // Convert 0x12 to 0x121200.
cb1 := int32(src.Cb[ci]) - 128
cr1 := int32(src.Cr[ci]) - 128
- r := (yy1 + 91881*cr1) >> 16
- g := (yy1 - 22554*cb1 - 46802*cr1) >> 16
- b := (yy1 + 116130*cb1) >> 16
- if r < 0 {
- r = 0
- } else if r > 255 {
- r = 255
+
+ // The bit twiddling below is equivalent to
+ //
+ // r := (yy1 + 91881*cr1) >> 16
+ // if r < 0 {
+ // r = 0
+ // } else if r > 0xff {
+ // r = ^int32(0)
+ // }
+ //
+ // but uses fewer branches and is faster.
+ // Note that the uint8 type conversion in the return
+ // statement will convert ^int32(0) to 0xff.
+ // The code below to compute g and b uses a similar pattern.
+ r := yy1 + 91881*cr1
+ if uint32(r)&0xff000000 == 0 {
+ r >>= 16
+ } else {
+ r = ^(r >> 31)
}
- if g < 0 {
- g = 0
- } else if g > 255 {
- g = 255
+
+ g := yy1 - 22554*cb1 - 46802*cr1
+ if uint32(g)&0xff000000 == 0 {
+ g >>= 16
+ } else {
+ g = ^(g >> 31)
}
- if b < 0 {
- b = 0
- } else if b > 255 {
- b = 255
+
+ b := yy1 + 116130*cb1
+ if uint32(b)&0xff000000 == 0 {
+ b >>= 16
+ } else {
+ b = ^(b >> 31)
}
- dpix[x+0] = uint8(r)
- dpix[x+1] = uint8(g)
- dpix[x+2] = uint8(b)
- dpix[x+3] = 255
+ // use a temp slice to hint to the compiler that a single bounds check suffices
+ rgba := dpix[x : x+4 : len(dpix)]
+ rgba[0] = uint8(r)
+ rgba[1] = uint8(g)
+ rgba[2] = uint8(b)
+ rgba[3] = 255
}
}
@@ -122,32 +158,50 @@ func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
ci := ciBase + sx/2
// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
- yy1 := int32(src.Y[yi]) * 0x10100 // Convert 0x12 to 0x121200.
+ yy1 := int32(src.Y[yi]) * 0x010100 // Convert 0x12 to 0x121200.
cb1 := int32(src.Cb[ci]) - 128
cr1 := int32(src.Cr[ci]) - 128
- r := (yy1 + 91881*cr1) >> 16
- g := (yy1 - 22554*cb1 - 46802*cr1) >> 16
- b := (yy1 + 116130*cb1) >> 16
- if r < 0 {
- r = 0
- } else if r > 255 {
- r = 255
+
+ // The bit twiddling below is equivalent to
+ //
+ // r := (yy1 + 91881*cr1) >> 16
+ // if r < 0 {
+ // r = 0
+ // } else if r > 0xff {
+ // r = ^int32(0)
+ // }
+ //
+ // but uses fewer branches and is faster.
+ // Note that the uint8 type conversion in the return
+ // statement will convert ^int32(0) to 0xff.
+ // The code below to compute g and b uses a similar pattern.
+ r := yy1 + 91881*cr1
+ if uint32(r)&0xff000000 == 0 {
+ r >>= 16
+ } else {
+ r = ^(r >> 31)
}
- if g < 0 {
- g = 0
- } else if g > 255 {
- g = 255
+
+ g := yy1 - 22554*cb1 - 46802*cr1
+ if uint32(g)&0xff000000 == 0 {
+ g >>= 16
+ } else {
+ g = ^(g >> 31)
}
- if b < 0 {
- b = 0
- } else if b > 255 {
- b = 255
+
+ b := yy1 + 116130*cb1
+ if uint32(b)&0xff000000 == 0 {
+ b >>= 16
+ } else {
+ b = ^(b >> 31)
}
- dpix[x+0] = uint8(r)
- dpix[x+1] = uint8(g)
- dpix[x+2] = uint8(b)
- dpix[x+3] = 255
+ // use a temp slice to hint to the compiler that a single bounds check suffices
+ rgba := dpix[x : x+4 : len(dpix)]
+ rgba[0] = uint8(r)
+ rgba[1] = uint8(g)
+ rgba[2] = uint8(b)
+ rgba[3] = 255
}
}
@@ -160,32 +214,50 @@ func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
- yy1 := int32(src.Y[yi]) * 0x10100 // Convert 0x12 to 0x121200.
+ yy1 := int32(src.Y[yi]) * 0x010100 // Convert 0x12 to 0x121200.
cb1 := int32(src.Cb[ci]) - 128
cr1 := int32(src.Cr[ci]) - 128
- r := (yy1 + 91881*cr1) >> 16
- g := (yy1 - 22554*cb1 - 46802*cr1) >> 16
- b := (yy1 + 116130*cb1) >> 16
- if r < 0 {
- r = 0
- } else if r > 255 {
- r = 255
+
+ // The bit twiddling below is equivalent to
+ //
+ // r := (yy1 + 91881*cr1) >> 16
+ // if r < 0 {
+ // r = 0
+ // } else if r > 0xff {
+ // r = ^int32(0)
+ // }
+ //
+ // but uses fewer branches and is faster.
+ // Note that the uint8 type conversion in the return
+ // statement will convert ^int32(0) to 0xff.
+ // The code below to compute g and b uses a similar pattern.
+ r := yy1 + 91881*cr1
+ if uint32(r)&0xff000000 == 0 {
+ r >>= 16
+ } else {
+ r = ^(r >> 31)
}
- if g < 0 {
- g = 0
- } else if g > 255 {
- g = 255
+
+ g := yy1 - 22554*cb1 - 46802*cr1
+ if uint32(g)&0xff000000 == 0 {
+ g >>= 16
+ } else {
+ g = ^(g >> 31)
}
- if b < 0 {
- b = 0
- } else if b > 255 {
- b = 255
+
+ b := yy1 + 116130*cb1
+ if uint32(b)&0xff000000 == 0 {
+ b >>= 16
+ } else {
+ b = ^(b >> 31)
}
- dpix[x+0] = uint8(r)
- dpix[x+1] = uint8(g)
- dpix[x+2] = uint8(b)
- dpix[x+3] = 255
+ // use a temp slice to hint to the compiler that a single bounds check suffices
+ rgba := dpix[x : x+4 : len(dpix)]
+ rgba[0] = uint8(r)
+ rgba[1] = uint8(g)
+ rgba[2] = uint8(b)
+ rgba[3] = 255
}
}