// A color JPEG image has Y, Cb and Cr components.
nColorComponent = 3
- // We only support 4:4:4, 4:2:2 and 4:2:0 downsampling, and therefore the
+ // We only support 4:4:4, 4:4:0, 4:2:2 and 4:2:0 downsampling, and therefore the
// number of luma samples per chroma sample is at most 2 in the horizontal
// and 2 in the vertical direction.
maxH = 2
if d.nComp == nGrayComponent {
continue
}
- // For color images, we only support 4:4:4, 4:2:2 or 4:2:0 chroma
+ // For color images, we only support 4:4:4, 4:4:0, 4:2:2 or 4:2:0 chroma
// downsampling ratios. This implies that the (h, v) values for the Y
- // component are either (1, 1), (2, 1) or (2, 2), and the (h, v)
+ // component are either (1, 1), (1, 2), (2, 1) or (2, 2), and the (h, v)
// values for the Cr and Cb components must be (1, 1).
if i == 0 {
- if hv != 0x11 && hv != 0x21 && hv != 0x22 {
+ if hv != 0x11 && hv != 0x21 && hv != 0x22 && hv != 0x12 {
return UnsupportedError("luma downsample ratio")
}
} else if hv != 0x11 {
return
}
var subsampleRatio image.YCbCrSubsampleRatio
- switch h0 * v0 {
- case 1:
+ switch {
+ case h0 == 1 && v0 == 1:
subsampleRatio = image.YCbCrSubsampleRatio444
- case 2:
+ case h0 == 1 && v0 == 2:
+ subsampleRatio = image.YCbCrSubsampleRatio440
+ case h0 == 2 && v0 == 1:
subsampleRatio = image.YCbCrSubsampleRatio422
- case 4:
+ case h0 == 2 && v0 == 2:
subsampleRatio = image.YCbCrSubsampleRatio420
default:
panic("unreachable")
} else {
switch i {
case 0:
- mx0 := h0*mx + (j % 2)
- my0 := v0*my + (j / 2)
+ mx0, my0 := h0*mx, v0*my
+ if h0 == 1 {
+ my0 += j
+ } else {
+ mx0 += j % 2
+ my0 += j / 2
+ }
idct(d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride, &b)
case 1:
idct(d.img3.Cb[8*(my*d.img3.CStride+mx):], d.img3.CStride, &b)
YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
YCbCrSubsampleRatio422
YCbCrSubsampleRatio420
+ YCbCrSubsampleRatio440
)
func (s YCbCrSubsampleRatio) String() string {
return "YCbCrSubsampleRatio422"
case YCbCrSubsampleRatio420:
return "YCbCrSubsampleRatio420"
+ case YCbCrSubsampleRatio440:
+ return "YCbCrSubsampleRatio440"
}
return "YCbCrSubsampleRatioUnknown"
}
// For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
// For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
// For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
+// For 4:4:0, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/2.
type YCbCr struct {
Y, Cb, Cr []uint8
YStride int
return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
case YCbCrSubsampleRatio420:
return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
+ case YCbCrSubsampleRatio440:
+ return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
}
// Default to 4:4:4 subsampling.
return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
case YCbCrSubsampleRatio420:
cw = (r.Max.X+1)/2 - r.Min.X/2
ch = (r.Max.Y+1)/2 - r.Min.Y/2
+ case YCbCrSubsampleRatio440:
+ cw = w
+ ch = (r.Max.Y+1)/2 - r.Min.Y/2
default:
// Default to 4:4:4 subsampling.
cw = w