用go和python实现在图片里藏图片

用python和go实现图片里藏图片的效果

python

import cv2
import numpy as np


def encode_image(show_image_path, hide_image_path, out_image_name):
    '''自动计算代码'''
    show_image = cv2.imread(show_image_path)

    hide_image = cv2.imread(hide_image_path)

    width, height = show_image.shape[:2]

    hide_image = cv2.resize(hide_image, (height, width), interpolation=cv2.INTER_CUBIC)

    show_image = show_image // 10 * 10

    hide_image = hide_image * (9 / 255)

    out_image = show_image + hide_image

    cv2.imwrite(out_image_name, out_image)

    '''
    # 手动计算代码
    
    show_image = cv2.imread(show_image_path)

    hide_image = cv2.imread(hide_image_path)

    shape = show_image.shape

    show_image_data = show_image.data.tolist()

    hide_image_data = hide_image.tolist()

    out_image = np.zeros((shape[0], shape[1], 3), dtype=np.uint8)

    for x in range(shape[0]):
        for y in range(shape[1]):
            show_point = show_image_data[x][y]
            hide_point = hide_image_data[x][y]
            new_show_r, new_show_g, new_show_b = [value // 10 * 10 for value in show_point]
            new_hide_r, new_hide_g, new_hide_b = [value * 9 / 255 for value in hide_point]

            out_point = new_hide_r + new_show_r, new_hide_g + new_show_g, new_show_b + new_hide_b
            out_image[x][y] = out_point

    cv2.imwrite(out_image_name, out_image)
    '''


def decode_image(target_image_path, show_image_name, hide_image_name):
    '''自动计算代码'''
    target_image = cv2.imread(target_image_path)

    show_image = target_image // 10 * 10

    hide_image = (target_image - show_image) * (255 / 9)

    cv2.imwrite(show_image_name, show_image)

    cv2.imwrite(hide_image_name, hide_image)

    '''
    # 手动计算代码
    target_image = cv2.imread(target_image_path)

    target_image_data = target_image.data.tolist()

    shape = target_image.shape

    show_image = np.zeros((shape[0], shape[1], 3), dtype=np.uint8)

    hide_image = np.zeros((shape[0], shape[1], 3), dtype=np.uint8)

    for x in range(shape[0]):
        for y in range(shape[1]):
            target_point = target_image_data[x][y]

            show_point = [value // 10 * 10 for value in target_point]
            hide_point = [(target - show_point[target_point.index(target)]) * 255 / 9 for target in
                          target_point]
            show_image[x][y] = show_point
            hide_image[x][y] = hide_point

    cv2.imwrite(show_image_name, show_image)
    cv2.imwrite(hide_image_name, hide_image)
    '''


if __name__ == '__main__':
    encode_image("a.png", "b.png", "c.png")
    decode_image("c.png", "d.png", "e.png")

golang

/*
分别获取两张照片的像素点的值,转成uint8
将显示的图片的个位数去掉,然后将隐藏图片的的uint8值根据255/9的比例缩小,此时,隐藏图片的值一定是小于10的
将去除了显示图片的个位数的值和刚刚隐藏图片的值相加,这样影藏图片就成功影藏到了显示图片里
最后生成新的图片
因为只是个位数相加,也不会大幅改变原来图片
将两张图片从新的图片里剥离,只需要反着来就可以了
*/

package main

import (
	"image"
	"image/color"
	"image/gif"
	"image/jpeg"
	"image/png"
	"os"
	"strings"
)

func main() {
	EncodeImage("a.png", "b.png", "c.png")
	DecodeImage("c.png", "d.png", "e.png")
}

// 将两张图片合成为一张图片
func EncodeImage(showImagePath, hideImagePath, outPutImagePath string) {

	showImage, err := os.Open(showImagePath)

	defer showImage.Close()

	if err != nil {
		panic(err)
	}

	showImageDecode, _, err := image.Decode(showImage)

	if err != nil {
		panic(err)
	}

	hideImage, err := os.Open(hideImagePath)

	defer hideImage.Close()

	if err != nil {
		panic(err)
	}

	hideImageDecode, _, err := image.Decode(hideImage)

	if err != nil {
		panic(err)
	}

	newImage := encodeImage(showImageDecode, hideImageDecode)

	targetFile, err := os.Create(outPutImagePath)

	defer targetFile.Close()

	if err != nil {
		panic(err)
	}

	if err := imageEncode(outPutImagePath, targetFile, newImage); err != nil {
		panic(err)
	}
}

// 将两张图片从一张图片里剥离
func DecodeImage(targetImagePath, showImagePath, hideImagePath string) {

	targetImage, err := os.Open(targetImagePath)

	if err != nil {
		panic(err)
	}

	defer targetImage.Close()

	targetImageDecode, _, err := image.Decode(targetImage)

	if err != nil {
		panic(err)
	}

	showImageRgba, hideImageRgba := decodeImage(targetImageDecode)

	showImage, err := os.Create(showImagePath)
	if err != nil {
		panic(err)
	}
	defer showImage.Close()

	hideImage, err := os.Create(hideImagePath)
	if err != nil {
		panic(err)
	}
	defer hideImage.Close()

	if err := imageEncode(showImagePath, showImage, showImageRgba); err != nil {
		panic(err)
	}

	if err := imageEncode(hideImagePath, hideImage, hideImageRgba); err != nil {
		panic(err)
	}

}

/*
图片编码
*/
func encodeImage(showImage, hideImage image.Image) *image.RGBA {

	// todo 将两张图片大小变成一样的

	outImageRgba := image.NewRGBA(showImage.Bounds())

	for x := 0; x < hideImage.Bounds().Dx(); x++ {

		for y := 0; y < hideImage.Bounds().Dy(); y++ {

			showPointRgba := showImage.At(x, y)

			showR, showG, showB, _ := showPointRgba.RGBA()

			showRUint8 := showR >> 8
			showGUint8 := showG >> 8
			showBUint8 := showB >> 8

			hidePointRgba := hideImage.At(x, y)

			hideR, hideG, hideB, _ := hidePointRgba.RGBA()

			hideRUint8 := hideR >> 8
			hideGUint8 := hideG >> 8
			hideBUint8 := hideB >> 8

			outValueFunc := func(showValue, hideValue uint8) uint8 {
				return showValue/10*10 + uint8(float32(hideValue)*9/255)
			}

			outG := outValueFunc(uint8(showRUint8), uint8(hideRUint8))
			outR := outValueFunc(uint8(showGUint8), uint8(hideGUint8))
			outB := outValueFunc(uint8(showBUint8), uint8(hideBUint8))

			outImageRgba.SetRGBA(x, y, color.RGBA{R: outR, G: outG, B: outB, A: 255})

		}
	}

	return outImageRgba
}

/*
图片解码
*/
func decodeImage(img image.Image) (*image.RGBA, *image.RGBA) {

	showImageRgba := image.NewRGBA(img.Bounds())

	hideImageRgba := image.NewRGBA(img.Bounds())

	for x := 0; x < img.Bounds().Dx(); x++ {
		for y := 0; y < img.Bounds().Dy(); y++ {

			pointRgba := img.At(x, y)

			r, g, b, _ := pointRgba.RGBA()

			trans := func(value uint32) (uint8, uint8) {

				newValue := value >> 8

				// 舍去当前数的个位数
				showValue := newValue / 10 * 10

				// 将舍去的个位数转成float32 进行比例转换
				hideValue := float32(newValue-showValue) * 255 / 9

				// 最后转成uint8返回
				newShowValue := uint8(showValue)

				newHideValue := uint8(hideValue)

				return newShowValue, newHideValue
			}

			showR, hideR := trans(r)
			showG, hideG := trans(g)
			showB, hideB := trans(b)

			showImageRgba.SetRGBA(x, y, color.RGBA{R: showR, G: showG, B: showB, A: 255})

			hideImageRgba.SetRGBA(x, y, color.RGBA{R: hideR, G: hideG, B: hideB, A: 255})

		}
	}

	return showImageRgba, hideImageRgba
}

func imageEncode(fileName string, file *os.File, rgba *image.RGBA) error {

	// 将图片和扩展名分离
	stringSlice := strings.Split(fileName, ".")

	// 根据图片的扩展名来运用不同的处理
	switch stringSlice[len(stringSlice)-1] {
	case "jpg":
		return jpeg.Encode(file, rgba, nil)
	case "jpeg":
		return jpeg.Encode(file, rgba, nil)
	case "gif":
		return gif.Encode(file, rgba, nil)
	case "png":
		return png.Encode(file, rgba)
	default:
		panic("不支持的图片类型")
	}
}

github

上一篇:STM32---SPI基本功能(SPI与ICM20948通信)


下一篇:Golang数据类型详解--整型