-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathimage_core.go
128 lines (102 loc) · 3.34 KB
/
image_core.go
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package stegano
import (
"fmt"
"image"
u "github.com/scott-mescudi/stegano/pkg"
)
// EmbedDataIntoImage embeds the given data into the RGB channels of the specified image.
func (m *EmbedHandler) EmbedDataIntoImage(coverImage image.Image, data []byte, bitDepth uint8) (image.Image, error) {
if coverImage == nil {
return nil, ErrInvalidCoverImage
}
if m.concurrency <= 0 {
m.concurrency = 1
}
RGBchannels := u.ExtractRGBChannelsFromImageWithConCurrency(coverImage, m.concurrency)
if (len(data)*8)+32 > len(RGBchannels)*3*(int(bitDepth)+1) {
return nil, ErrDataTooLarge
}
embeddedRGBChannels, err := u.EmbedIntoRGBchannelsWithDepth(RGBchannels, data, bitDepth)
if err != nil {
return nil, err
}
return u.SaveImage(embeddedRGBChannels, coverImage.Bounds().Dy(), coverImage.Bounds().Dx())
}
// ExtractDataFromImage retrieves data embedded in the RGB channels of the specified image.
func (m *ExtractHandler) ExtractDataFromImage(coverImage image.Image, bitDepth uint8) ([]byte, error) {
if coverImage == nil {
return nil, ErrInvalidCoverImage
}
if m.concurrency <= 0 {
m.concurrency = 1
}
RGBchannels := u.ExtractRGBChannelsFromImageWithConCurrency(coverImage, m.concurrency)
data, err := u.ExtractDataFromRGBchannelsWithDepth(RGBchannels, bitDepth)
if err != nil {
return nil, err
}
lenData, err := u.GetlenOfData(data)
if err != nil || lenData == 0 {
return nil, err
}
var moddedData = make([]byte, 0, lenData)
defer func() {
if r := recover(); r != nil {
moddedData = nil
err = fmt.Errorf("fatal error: %v", r)
}
}()
for i := 4; i < lenData+4; i++ {
if i >= len(data) {
return nil, fmt.Errorf("index out of range while accessing data: %d", i)
}
moddedData = append(moddedData, data[i])
}
return moddedData, nil
}
// EmbedAtDepth embeds the provided data into a specific bit depth of the RGB channels of the image.
// Unlike other embedding methods, this modifies a single bit per channel at the specified depth.
func (m *EmbedHandler) EmbedAtDepth(coverimage image.Image, data []byte, depth uint8) (image.Image, error) {
if coverimage == nil {
return nil, ErrInvalidCoverImage
}
if m.concurrency <= 0 {
m.concurrency = 1
}
channels := u.ExtractRGBChannelsFromImageWithConCurrency(coverimage, m.concurrency)
if channels == nil {
return nil, ErrFailedToExtractRGB
}
ec, err := u.EmbedAtDepth(channels, data, depth)
if err != nil {
return nil, err
}
return u.SaveImage(ec, coverimage.Bounds().Dy(), coverimage.Bounds().Dx())
}
// ExtractAtDepth extracts data embedded at a specific bit depth from the RGB channels of an image.
// Only retrieves data from the specified bit depth. Returns the extracted data or an error if the process fails.
func (m *ExtractHandler) ExtractAtDepth(coverimage image.Image, depth uint8) ([]byte, error) {
if coverimage == nil {
return nil, ErrInvalidCoverImage
}
if m.concurrency <= 0 {
m.concurrency = 1
}
channels := u.ExtractRGBChannelsFromImageWithConCurrency(coverimage, m.concurrency)
if channels == nil {
return nil, ErrFailedToExtractRGB
}
emdata, err := u.ExtractAtDepth(channels, depth)
if err != nil {
return nil, err
}
lenData, err := u.GetlenOfData(emdata)
if err != nil || lenData == 0 {
return nil, err
}
var moddedData = make([]byte, 0)
for i := 4; i < lenData+4; i++ {
moddedData = append(moddedData, emdata[i])
}
return moddedData, nil
}