commit 144a85b3bee6c2db20d2c23fa2879cf41a118830 Author: JDierkse Date: Mon May 11 21:51:00 2020 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..851ef09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o.* +*.d.* +*.a.* +.*.swp +.AppleDouble +lib diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7da2786 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Makefiles"] + path = Makefiles + url = https://gogs.dierkse.nl/JDierkse/Makefiles.git diff --git a/Image/JpegImage.cpp b/Image/JpegImage.cpp new file mode 100644 index 0000000..8acfb44 --- /dev/null +++ b/Image/JpegImage.cpp @@ -0,0 +1,123 @@ +#include "JpegImage.h" + + +namespace Image { + +const static JOCTET EOI_BUFFER[1] = { JPEG_EOI }; + +JpegImage::JpegImage() +{ +} + +void JpegImage::SetImageData(const std::string& data) +{ + DecompressImage(data.c_str(), data.size()); +} + +unsigned int JpegImage::Width() const +{ + return m_width; +} + +unsigned int JpegImage::Height() const +{ + return m_height; +} + +unsigned int JpegImage::StrideX() const +{ + return m_strideX; +} + +unsigned int JpegImage::StrideY() const +{ + return m_strideY; +} + +const std::vector& JpegImage::Data() const +{ + return m_data; +} + +void JpegImage::InitSource(j_decompress_ptr pCinfo) +{ +} + +boolean JpegImage::FillInputBuffer(j_decompress_ptr pCinfo) +{ + SourceMgrPtr pSrc = reinterpret_cast(pCinfo->src); + pSrc->pub.next_input_byte = EOI_BUFFER; + pSrc->pub.bytes_in_buffer = 1; + return TRUE; +} + +void JpegImage::SkipInputData(j_decompress_ptr pCinfo, long numBytes) +{ + SourceMgrPtr pSrc = reinterpret_cast(pCinfo->src); + if (pSrc->pub.bytes_in_buffer < static_cast(numBytes)) + { + pSrc->pub.next_input_byte = EOI_BUFFER; + pSrc->pub.bytes_in_buffer = 1; + } + else + { + pSrc->pub.next_input_byte += numBytes; + pSrc->pub.bytes_in_buffer -= numBytes; + } +} + +void JpegImage::TermSource(j_decompress_ptr pCinfo) +{ +} + +void JpegImage::SetSourceMgr(j_decompress_ptr pCinfo, const char* pData, size_t len) const +{ + SourceMgrPtr pSrc; + if (pCinfo->src == 0) + pCinfo->src = (struct jpeg_source_mgr *)(*pCinfo->mem->alloc_small)(reinterpret_cast(pCinfo), JPOOL_PERMANENT, sizeof(SourceMgr)); + + pSrc = reinterpret_cast(pCinfo->src); + pSrc->pub.init_source = JpegImage::InitSource; + pSrc->pub.fill_input_buffer = JpegImage::FillInputBuffer; + pSrc->pub.skip_input_data = JpegImage::SkipInputData; + pSrc->pub.resync_to_restart = jpeg_resync_to_restart; + pSrc->pub.term_source = JpegImage::TermSource; + + pSrc->data = (const JOCTET *)pData; + pSrc->len = len; + pSrc->pub.bytes_in_buffer = len; + pSrc->pub.next_input_byte = pSrc->data; +} + +void JpegImage::DecompressImage(const char* pData, size_t len) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + + jerr.trace_level = 0; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + SetSourceMgr(&cinfo, pData, len); + + jpeg_read_header(&cinfo, TRUE); + jpeg_start_decompress(&cinfo); + + m_width = cinfo.image_width; + m_height = cinfo.image_height; + m_strideX = cinfo.num_components; + m_strideY = m_width * cinfo.num_components; + + m_data.resize(m_height * m_strideY); + + JSAMPROW scanlines[1]; + while (cinfo.output_scanline < cinfo.image_height) + { + scanlines[0] = reinterpret_cast(&m_data[cinfo.output_scanline * m_strideY]); + jpeg_read_scanlines(&cinfo, scanlines, 1); + } + + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); +} + +} // namespace Image diff --git a/Image/JpegImageCollection.cpp b/Image/JpegImageCollection.cpp new file mode 100644 index 0000000..1cd06c6 --- /dev/null +++ b/Image/JpegImageCollection.cpp @@ -0,0 +1,67 @@ +#include "JpegImageCollection.h" +#include + + +namespace Image { + +JpegImageCollection::JpegImageCollection(const std::vector& images) : + m_width(0), + m_height(0), + m_strideX(0), + m_strideY(0) +{ + if (images.size() == 0) + return; + + m_width = images[0].Width(); + m_strideX = images[0].StrideX(); + m_strideY = images[0].StrideY(); + + size_t height = images[0].Height(); + m_height = height * images.size(); + m_imageData.resize(m_strideY * m_height); + + std::vector::iterator outIterator = m_imageData.begin(); + for (std::vector::const_iterator it = images.begin(); it != images.end(); ++it) + outIterator = std::copy(it->Data().begin(), it->Data().end(), outIterator); +} + +void JpegImageCollection::Save(const std::string& fileName) +{ + if (m_width == 0 || m_height == 0 || m_strideX == 0 || m_strideY == 0) + return; + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + + FILE* outFile = fopen(fileName.c_str(), "wb"); + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, outFile); + + cinfo.image_width = m_width; + cinfo.image_height = m_height; + cinfo.input_components = m_strideX; + cinfo.in_color_space = JCS_RGB; + + jpeg_set_defaults( &cinfo ); + cinfo.num_components = 3; + cinfo.dct_method = JDCT_FLOAT; + jpeg_set_quality(&cinfo, 80, TRUE); + + jpeg_start_compress( &cinfo, TRUE ); + + JSAMPROW scanlines[1]; + while (cinfo.next_scanline < cinfo.image_height) + { + scanlines[0] = reinterpret_cast(&m_imageData[cinfo.next_scanline * m_strideY]); + jpeg_write_scanlines(&cinfo, scanlines, 1); + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + fclose(outFile); +} + +} // namespace Image diff --git a/Image/Makefile b/Image/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/Image/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 120000 index 0000000..6aa5187 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +Makefiles/Makefile \ No newline at end of file diff --git a/Makefile.conf b/Makefile.conf new file mode 100644 index 0000000..e337dbc --- /dev/null +++ b/Makefile.conf @@ -0,0 +1,9 @@ +# +# Makefile.conf +# + +LFLAGS += -lImage +LFLAGS += -L$(ROOTPATH)/lib/$(ARCH) +CFLAGS += -I$(ROOTPATH) -I$(ROOTPATH)/include + +DEBUGDIR := .debug diff --git a/Makefile.target b/Makefile.target new file mode 100644 index 0000000..1937557 --- /dev/null +++ b/Makefile.target @@ -0,0 +1,13 @@ +# +# Makefile.target +# + +Image.a.$(ARCH) : $(OBJECTS) + $(call build_target_library_arch,$@,$^) + +Image.a: + $(call build_target,$@) + +.DEFAULT_GOAL := Image.a + +TARGETS += Image.a diff --git a/Makefiles b/Makefiles new file mode 160000 index 0000000..cd9ef1a --- /dev/null +++ b/Makefiles @@ -0,0 +1 @@ +Subproject commit cd9ef1a1b0f7b88f36b0c51b4209d1859aca83aa diff --git a/include/JpegImage.h b/include/JpegImage.h new file mode 100644 index 0000000..61e57b2 --- /dev/null +++ b/include/JpegImage.h @@ -0,0 +1,55 @@ +#ifndef JPEGIMAGE_H +#define JPEGIMAGE_H + +#include // jpeglib issue +#include +#include +#include + + +namespace Image { + +class JpegImage +{ +public: + JpegImage(); + + void SetImageData(const std::string& data); + + unsigned int Width() const; + unsigned int Height() const; + unsigned int StrideX() const; + unsigned int StrideY() const; + const std::vector& Data() const; + +private: + struct SourceMgr + { + struct jpeg_source_mgr pub; + const JOCTET *data; + size_t len; + }; + typedef SourceMgr* SourceMgrPtr; + +private: + static void InitSource(j_decompress_ptr pCinfo); + static boolean FillInputBuffer(j_decompress_ptr pCinfo); + static void SkipInputData(j_decompress_ptr pCinfo, long numBytes); + static void TermSource(j_decompress_ptr pCinfo); + + void SetSourceMgr(j_decompress_ptr pCinfo, const char* pData, size_t len) const; + + void DecompressImage(const char* pData, size_t len); + +private: + unsigned int m_width; + unsigned int m_height; + unsigned int m_strideX; + unsigned int m_strideY; + + std::vector m_data; +}; + +} // namespace Image + +#endif // JPEGIMAGE_H diff --git a/include/JpegImageCollection.h b/include/JpegImageCollection.h new file mode 100644 index 0000000..9c3dc63 --- /dev/null +++ b/include/JpegImageCollection.h @@ -0,0 +1,30 @@ +#ifndef JPEGIMAGECOLLECTION_H +#define JPEGIMAGECOLLECTION_H + +#include "JpegImage.h" +#include +#include + + + +namespace Image { + +class JpegImageCollection +{ +public: + JpegImageCollection(const std::vector& images); + + void Save(const std::string& fileName); + +private: + size_t m_width; + size_t m_height; + size_t m_strideX; + size_t m_strideY; + + std::vector m_imageData; +}; + +} // namespace Image + +#endif // JPEGIMAGECOLLECTION_H