mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-29 13:48:54 +08:00
Inline image fixes; image mask; sampling change: pad with 0s if missing data
This commit is contained in:
parent
0e56876030
commit
94ba6a8f4f
@ -127,6 +127,24 @@ func (this *ContentStreamInlineImage) GetEncoder() (StreamEncoder, error) {
|
||||
return newEncoderFromInlineImage(this)
|
||||
}
|
||||
|
||||
// Is a mask ?
|
||||
// The image mask entry in the image dictionary specifies that the image data shall be used as a stencil
|
||||
// mask for painting in the current color. The mask data is 1bpc, grayscale.
|
||||
func (this *ContentStreamInlineImage) IsMask() (bool, error) {
|
||||
if this.ImageMask != nil {
|
||||
imMask, ok := this.ImageMask.(*PdfObjectBool)
|
||||
if !ok {
|
||||
common.Log.Debug("Image mask not a boolean")
|
||||
return false, errors.New("Invalid object type")
|
||||
}
|
||||
|
||||
return bool(*imMask), nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Export the inline image to Image which can be transformed or exported easily.
|
||||
// Page resources are needed to look up colorspace information.
|
||||
func (this *ContentStreamInlineImage) ToImage(resources *PdfPageResources) (*Image, error) {
|
||||
@ -164,30 +182,43 @@ func (this *ContentStreamInlineImage) ToImage(resources *PdfPageResources) (*Ima
|
||||
}
|
||||
image.Width = int64(*width)
|
||||
|
||||
// BPC.
|
||||
if this.BitsPerComponent == nil {
|
||||
common.Log.Debug("Inline Bits per component missing - assuming 8")
|
||||
image.BitsPerComponent = 8
|
||||
} else {
|
||||
bpc, ok := this.BitsPerComponent.(*PdfObjectInteger)
|
||||
if !ok {
|
||||
common.Log.Debug("Error invalid bits per component value, type %T", this.BitsPerComponent)
|
||||
return nil, errors.New("BPC Type error")
|
||||
}
|
||||
image.BitsPerComponent = int64(*bpc)
|
||||
// Image mask?
|
||||
isMask, err := this.IsMask()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Color components.
|
||||
if this.ColorSpace != nil {
|
||||
cs, err := this.GetColorSpace(resources)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
image.ColorComponents = cs.GetNumComponents()
|
||||
} else {
|
||||
// Default gray if not specified.
|
||||
common.Log.Debug("Inline Image colorspace not specified - assuming 1 color component")
|
||||
if isMask {
|
||||
// Masks are grayscale 1bpc.
|
||||
image.BitsPerComponent = 1
|
||||
image.ColorComponents = 1
|
||||
} else {
|
||||
|
||||
// BPC.
|
||||
if this.BitsPerComponent == nil {
|
||||
common.Log.Debug("Inline Bits per component missing - assuming 8")
|
||||
image.BitsPerComponent = 8
|
||||
} else {
|
||||
bpc, ok := this.BitsPerComponent.(*PdfObjectInteger)
|
||||
if !ok {
|
||||
common.Log.Debug("Error invalid bits per component value, type %T", this.BitsPerComponent)
|
||||
return nil, errors.New("BPC Type error")
|
||||
}
|
||||
image.BitsPerComponent = int64(*bpc)
|
||||
}
|
||||
|
||||
// Color components.
|
||||
if this.ColorSpace != nil {
|
||||
cs, err := this.GetColorSpace(resources)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
image.ColorComponents = cs.GetNumComponents()
|
||||
} else {
|
||||
// Default gray if not specified.
|
||||
common.Log.Debug("Inline Image colorspace not specified - assuming 1 color component")
|
||||
image.ColorComponents = 1
|
||||
}
|
||||
}
|
||||
|
||||
image.Data = decoded
|
||||
|
@ -186,5 +186,11 @@ func ResampleUint32(data []uint32, bitsPerInputSample int, bitsPerOutputSample i
|
||||
}
|
||||
}
|
||||
|
||||
// If there are partial output samples, pad with 0s.
|
||||
if bitsLeftPerSample > 0 && bitsLeftPerSample < bitsPerOutputSample {
|
||||
sample <<= uint(bitsLeftPerSample)
|
||||
samples = append(samples, sample)
|
||||
}
|
||||
|
||||
return samples
|
||||
}
|
||||
|
@ -86,9 +86,10 @@ func TestResamplingBytes(t *testing.T) {
|
||||
}
|
||||
|
||||
type TestResamplingTest2 struct {
|
||||
InputData []uint32
|
||||
BitsPerSample int
|
||||
Expected []uint32
|
||||
InputData []uint32
|
||||
BitsPerInputSample int
|
||||
BitsPerOutputSample int
|
||||
Expected []uint32
|
||||
}
|
||||
|
||||
// Test resampling example data with different bits per sample.
|
||||
@ -122,22 +123,40 @@ func TestResamplingUint32(t *testing.T) {
|
||||
// 0xde 0xad 0xbe 0xef 0x15 0x13 0x37
|
||||
|
||||
testcases := []TestResamplingTest2{
|
||||
{[]uint32{0xB55D2A00}, 1, []uint32{1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{[]uint32{0xB55D2A00}, 2, []uint32{2, 3, 1, 1, 1, 1, 3, 1, 0, 2, 2, 2, 0, 0, 0, 0}},
|
||||
{[]uint32{0xB55D2A00}, 3, []uint32{5, 5, 2, 5, 6, 4, 5, 2, 0, 0}},
|
||||
{[]uint32{0xB55D2A00}, 4, []uint32{11, 5, 5, 13, 2, 10, 0, 0}},
|
||||
{[]uint32{0xB55D2A00}, 5, []uint32{22, 21, 14, 18, 20, 0}},
|
||||
{[]uint32{0xB55D2A00}, 8, []uint32{0xB5, 0x5D, 0x2A, 0x00}},
|
||||
{[]uint32{0xB55D2A00}, 12, []uint32{2901, 3370}},
|
||||
{[]uint32{0xB55D2A00}, 13, []uint32{5803, 5288}},
|
||||
{[]uint32{0xB55D2A00}, 16, []uint32{0xB55D, 0x2A00}},
|
||||
{[]uint32{0xB55D2A00}, 24, []uint32{0xB55D2A}},
|
||||
{[]uint32{0xdeadbeef, 0x15133720}, 24, []uint32{0xdeadbe, 0xef1513}},
|
||||
{[]uint32{0xdeadbeef, 0x15133720}, 32, []uint32{0xdeadbeef, 0x15133720c}},
|
||||
{[]uint32{0xB55D2A00}, 32, 1, []uint32{1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{[]uint32{0xB55D2A00}, 32, 2, []uint32{2, 3, 1, 1, 1, 1, 3, 1, 0, 2, 2, 2, 0, 0, 0, 0}},
|
||||
{[]uint32{0xB55D2A00}, 32, 3, []uint32{5, 5, 2, 5, 6, 4, 5, 2, 0, 0}},
|
||||
{[]uint32{0xB55D2A00}, 32, 4, []uint32{11, 5, 5, 13, 2, 10, 0, 0}},
|
||||
{[]uint32{0xB55D2A00}, 32, 5, []uint32{22, 21, 14, 18, 20, 0}},
|
||||
{[]uint32{0xB55D2A00}, 32, 8, []uint32{0xB5, 0x5D, 0x2A, 0x00}},
|
||||
{[]uint32{0xB55D2A00}, 32, 12, []uint32{2901, 3370}},
|
||||
{[]uint32{0xB55D2A00}, 32, 13, []uint32{5803, 5288}},
|
||||
{[]uint32{0xB55D2A00}, 32, 16, []uint32{0xB55D, 0x2A00}},
|
||||
{[]uint32{0xB55D2A00}, 32, 24, []uint32{0xB55D2A}},
|
||||
{[]uint32{0xdeadbeef, 0x15133720}, 32, 24, []uint32{0xdeadbe, 0xef1513}},
|
||||
{[]uint32{0xdeadbeef, 0x15133720}, 32, 32, []uint32{0xdeadbeef, 0x15133720}},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
b := ResampleUint32(testcase.InputData, 32, testcase.BitsPerSample)
|
||||
b := ResampleUint32(testcase.InputData, testcase.BitsPerInputSample, testcase.BitsPerOutputSample)
|
||||
fmt.Println(b)
|
||||
if !samplesEqual(b, testcase.Expected) {
|
||||
//t.Errorf("Test case failed. Got: % d, expected: % d", b, testcase.Expected)
|
||||
t.Errorf("Test case failed. Got: % X, expected: % X", b, testcase.Expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test resampling example data with different bits per sample.
|
||||
// Input is in uint32, certain number of bits.
|
||||
func TestResamplingUint32xx(t *testing.T) {
|
||||
testcases := []TestResamplingTest2{
|
||||
{[]uint32{0, 0, 0}, 1, 8, []uint32{0}},
|
||||
{[]uint32{0, 1, 0}, 1, 8, []uint32{64}},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
b := ResampleUint32(testcase.InputData, testcase.BitsPerInputSample, testcase.BitsPerOutputSample)
|
||||
fmt.Println(b)
|
||||
if !samplesEqual(b, testcase.Expected) {
|
||||
t.Errorf("Test case failed. Got: % d, expected: % d", b, testcase.Expected)
|
||||
|
Loading…
x
Reference in New Issue
Block a user