-Replaced tinyjpg for jpgd (public domain), fixes progressive encoded jpgs and speeds up. Closes #2040
-Removed support of loading BitMap as image, now it must be load as a pnm, also closes #2040
This commit is contained in:
parent
b988f016fd
commit
e8fbf39f88
|
@ -1636,12 +1636,16 @@ int64_t String::to_int64() const {
|
|||
return integer*sign;
|
||||
}
|
||||
|
||||
int String::to_int(const char* p_str) {
|
||||
int String::to_int(const char* p_str,int p_len) {
|
||||
|
||||
|
||||
int to=0;
|
||||
while(p_str[to]!=0 && p_str[to]!='.')
|
||||
to++;
|
||||
if (p_len>=0)
|
||||
to=p_len;
|
||||
else {
|
||||
while(p_str[to]!=0 && p_str[to]!='.')
|
||||
to++;
|
||||
}
|
||||
|
||||
|
||||
int integer=0;
|
||||
|
|
|
@ -144,7 +144,7 @@ public:
|
|||
int to_int() const;
|
||||
|
||||
int64_t to_int64() const;
|
||||
static int to_int(const char* p_str);
|
||||
static int to_int(const char* p_str, int p_len=-1);
|
||||
static double to_double(const char* p_str);
|
||||
static double to_double(const CharType* p_str, const CharType **r_end=NULL);
|
||||
static int64_t to_int(const CharType* p_str,int p_len=-1);
|
||||
|
|
|
@ -12,11 +12,13 @@ SConscript('windows/SCsub');
|
|||
SConscript('gles2/SCsub');
|
||||
SConscript('gl_context/SCsub');
|
||||
SConscript('openssl/SCsub');
|
||||
SConscript('pnm/SCsub');
|
||||
|
||||
if (env["png"]=="yes"):
|
||||
SConscript("png/SCsub");
|
||||
if (env["jpg"]=="yes"):
|
||||
SConscript("jpg/SCsub");
|
||||
#SConscript("jpg/SCsub");
|
||||
SConscript("jpegd/SCsub");
|
||||
if (env["webp"]=="yes"):
|
||||
SConscript("webp/SCsub");
|
||||
SConscript("dds/SCsub");
|
||||
|
|
|
@ -2,9 +2,8 @@ Import('env')
|
|||
|
||||
|
||||
jpg_sources = [
|
||||
"jpg/tinyjpeg.c",
|
||||
"jpg/jidctflt.c",
|
||||
"jpg/image_loader_jpg.cpp"
|
||||
"jpegd/jpgd.cpp",
|
||||
"jpegd/image_loader_jpegd.cpp"
|
||||
]
|
||||
|
||||
env.drivers_sources+=jpg_sources
|
|
@ -0,0 +1,108 @@
|
|||
/*************************************************/
|
||||
/* image_loader_jpg.cpp */
|
||||
/*************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/*************************************************/
|
||||
/* Source code within this file is: */
|
||||
/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
|
||||
/* All Rights Reserved. */
|
||||
/*************************************************/
|
||||
|
||||
#include "image_loader_jpegd.h"
|
||||
|
||||
#include "print_string.h"
|
||||
#include "os/os.h"
|
||||
#include "jpgd.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) {
|
||||
|
||||
|
||||
DVector<uint8_t> src_image;
|
||||
int src_image_len = f->get_len();
|
||||
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
|
||||
src_image.resize(src_image_len);
|
||||
|
||||
DVector<uint8_t>::Write w = src_image.write();
|
||||
|
||||
f->get_buffer(&w[0],src_image_len);
|
||||
|
||||
f->close();
|
||||
|
||||
|
||||
|
||||
jpgd::jpeg_decoder_mem_stream mem_stream(w.ptr(),src_image_len);
|
||||
|
||||
jpgd::jpeg_decoder decoder(&mem_stream);
|
||||
|
||||
if (decoder.get_error_code() != jpgd::JPGD_SUCCESS) {
|
||||
return ERR_CANT_OPEN;
|
||||
}
|
||||
|
||||
const int image_width = decoder.get_width();
|
||||
const int image_height = decoder.get_height();
|
||||
int comps = decoder.get_num_components();
|
||||
if (comps==3)
|
||||
comps=4; //weird
|
||||
|
||||
if (decoder.begin_decoding() != jpgd::JPGD_SUCCESS)
|
||||
return ERR_FILE_CORRUPT;
|
||||
|
||||
const int dst_bpl = image_width * comps;
|
||||
|
||||
DVector<uint8_t> data;
|
||||
|
||||
data.resize(dst_bpl * image_height);
|
||||
|
||||
DVector<uint8_t>::Write dw = data.write();
|
||||
|
||||
jpgd::uint8 *pImage_data = (jpgd::uint8*)dw.ptr();
|
||||
|
||||
for (int y = 0; y < image_height; y++)
|
||||
{
|
||||
const jpgd::uint8* pScan_line;
|
||||
uint scan_line_len;
|
||||
if (decoder.decode((const void**)&pScan_line, &scan_line_len) != jpgd::JPGD_SUCCESS)
|
||||
{
|
||||
return ERR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
jpgd::uint8 *pDst = pImage_data + y * dst_bpl;
|
||||
memcpy(pDst, pScan_line, dst_bpl);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//all good
|
||||
|
||||
Image::Format fmt;
|
||||
if (comps==1)
|
||||
fmt=Image::FORMAT_GRAYSCALE;
|
||||
else
|
||||
fmt=Image::FORMAT_RGBA;
|
||||
|
||||
dw = DVector<uint8_t>::Write();
|
||||
w = DVector<uint8_t>::Write();
|
||||
|
||||
p_image->create(image_width,image_height,0,fmt,data);
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const {
|
||||
|
||||
p_extensions->push_back("jpg");
|
||||
p_extensions->push_back("jpeg");
|
||||
}
|
||||
|
||||
|
||||
ImageLoaderJPG::ImageLoaderJPG() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,319 @@
|
|||
// jpgd.h - C++ class for JPEG decompression.
|
||||
// Public domain, Rich Geldreich <richgel99@gmail.com>
|
||||
#ifndef JPEG_DECODER_H
|
||||
#define JPEG_DECODER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define JPGD_NORETURN __declspec(noreturn)
|
||||
#elif defined(__GNUC__)
|
||||
#define JPGD_NORETURN __attribute__ ((noreturn))
|
||||
#else
|
||||
#define JPGD_NORETURN
|
||||
#endif
|
||||
|
||||
namespace jpgd
|
||||
{
|
||||
typedef unsigned char uint8;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint;
|
||||
typedef signed int int32;
|
||||
|
||||
// Loads a JPEG image from a memory buffer or a file.
|
||||
// req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA).
|
||||
// On return, width/height will be set to the image's dimensions, and actual_comps will be set to the either 1 (grayscale) or 3 (RGB).
|
||||
// Notes: For more control over where and how the source data is read, see the decompress_jpeg_image_from_stream() function below, or call the jpeg_decoder class directly.
|
||||
// Requesting a 8 or 32bpp image is currently a little faster than 24bpp because the jpeg_decoder class itself currently always unpacks to either 8 or 32bpp.
|
||||
unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps);
|
||||
unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps);
|
||||
|
||||
// Success/failure error codes.
|
||||
enum jpgd_status
|
||||
{
|
||||
JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1,
|
||||
JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE,
|
||||
JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS,
|
||||
JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH,
|
||||
JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER,
|
||||
JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS,
|
||||
JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE,
|
||||
JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER, JPGD_ASSERTION_ERROR,
|
||||
JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM
|
||||
};
|
||||
|
||||
// Input stream interface.
|
||||
// Derive from this class to read input data from sources other than files or memory. Set m_eof_flag to true when no more data is available.
|
||||
// The decoder is rather greedy: it will keep on calling this method until its internal input buffer is full, or until the EOF flag is set.
|
||||
// It the input stream contains data after the JPEG stream's EOI (end of image) marker it will probably be pulled into the internal buffer.
|
||||
// Call the get_total_bytes_read() method to determine the actual size of the JPEG stream after successful decoding.
|
||||
class jpeg_decoder_stream
|
||||
{
|
||||
public:
|
||||
jpeg_decoder_stream() { }
|
||||
virtual ~jpeg_decoder_stream() { }
|
||||
|
||||
// The read() method is called when the internal input buffer is empty.
|
||||
// Parameters:
|
||||
// pBuf - input buffer
|
||||
// max_bytes_to_read - maximum bytes that can be written to pBuf
|
||||
// pEOF_flag - set this to true if at end of stream (no more bytes remaining)
|
||||
// Returns -1 on error, otherwise return the number of bytes actually written to the buffer (which may be 0).
|
||||
// Notes: This method will be called in a loop until you set *pEOF_flag to true or the internal buffer is full.
|
||||
virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag) = 0;
|
||||
};
|
||||
|
||||
// stdio FILE stream class.
|
||||
class jpeg_decoder_file_stream : public jpeg_decoder_stream
|
||||
{
|
||||
jpeg_decoder_file_stream(const jpeg_decoder_file_stream &);
|
||||
jpeg_decoder_file_stream &operator =(const jpeg_decoder_file_stream &);
|
||||
|
||||
FILE *m_pFile;
|
||||
bool m_eof_flag, m_error_flag;
|
||||
|
||||
public:
|
||||
jpeg_decoder_file_stream();
|
||||
virtual ~jpeg_decoder_file_stream();
|
||||
|
||||
bool open(const char *Pfilename);
|
||||
void close();
|
||||
|
||||
virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
|
||||
};
|
||||
|
||||
// Memory stream class.
|
||||
class jpeg_decoder_mem_stream : public jpeg_decoder_stream
|
||||
{
|
||||
const uint8 *m_pSrc_data;
|
||||
uint m_ofs, m_size;
|
||||
|
||||
public:
|
||||
jpeg_decoder_mem_stream() : m_pSrc_data(NULL), m_ofs(0), m_size(0) { }
|
||||
jpeg_decoder_mem_stream(const uint8 *pSrc_data, uint size) : m_pSrc_data(pSrc_data), m_ofs(0), m_size(size) { }
|
||||
|
||||
virtual ~jpeg_decoder_mem_stream() { }
|
||||
|
||||
bool open(const uint8 *pSrc_data, uint size);
|
||||
void close() { m_pSrc_data = NULL; m_ofs = 0; m_size = 0; }
|
||||
|
||||
virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
|
||||
};
|
||||
|
||||
// Loads JPEG file from a jpeg_decoder_stream.
|
||||
unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps);
|
||||
|
||||
enum
|
||||
{
|
||||
JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4,
|
||||
JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384
|
||||
};
|
||||
|
||||
typedef int16 jpgd_quant_t;
|
||||
typedef int16 jpgd_block_t;
|
||||
|
||||
class jpeg_decoder
|
||||
{
|
||||
public:
|
||||
// Call get_error_code() after constructing to determine if the stream is valid or not. You may call the get_width(), get_height(), etc.
|
||||
// methods after the constructor is called. You may then either destruct the object, or begin decoding the image by calling begin_decoding(), then decode() on each scanline.
|
||||
jpeg_decoder(jpeg_decoder_stream *pStream);
|
||||
|
||||
~jpeg_decoder();
|
||||
|
||||
// Call this method after constructing the object to begin decompression.
|
||||
// If JPGD_SUCCESS is returned you may then call decode() on each scanline.
|
||||
int begin_decoding();
|
||||
|
||||
// Returns the next scan line.
|
||||
// For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1).
|
||||
// Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4).
|
||||
// Returns JPGD_SUCCESS if a scan line has been returned.
|
||||
// Returns JPGD_DONE if all scan lines have been returned.
|
||||
// Returns JPGD_FAILED if an error occurred. Call get_error_code() for a more info.
|
||||
int decode(const void** pScan_line, uint* pScan_line_len);
|
||||
|
||||
inline jpgd_status get_error_code() const { return m_error_code; }
|
||||
|
||||
inline int get_width() const { return m_image_x_size; }
|
||||
inline int get_height() const { return m_image_y_size; }
|
||||
|
||||
inline int get_num_components() const { return m_comps_in_frame; }
|
||||
|
||||
inline int get_bytes_per_pixel() const { return m_dest_bytes_per_pixel; }
|
||||
inline int get_bytes_per_scan_line() const { return m_image_x_size * get_bytes_per_pixel(); }
|
||||
|
||||
// Returns the total number of bytes actually consumed by the decoder (which should equal the actual size of the JPEG file).
|
||||
inline int get_total_bytes_read() const { return m_total_bytes_read; }
|
||||
|
||||
private:
|
||||
jpeg_decoder(const jpeg_decoder &);
|
||||
jpeg_decoder &operator =(const jpeg_decoder &);
|
||||
|
||||
typedef void (*pDecode_block_func)(jpeg_decoder *, int, int, int);
|
||||
|
||||
struct huff_tables
|
||||
{
|
||||
bool ac_table;
|
||||
uint look_up[256];
|
||||
uint look_up2[256];
|
||||
uint8 code_size[256];
|
||||
uint tree[512];
|
||||
};
|
||||
|
||||
struct coeff_buf
|
||||
{
|
||||
uint8 *pData;
|
||||
int block_num_x, block_num_y;
|
||||
int block_len_x, block_len_y;
|
||||
int block_size;
|
||||
};
|
||||
|
||||
struct mem_block
|
||||
{
|
||||
mem_block *m_pNext;
|
||||
size_t m_used_count;
|
||||
size_t m_size;
|
||||
char m_data[1];
|
||||
};
|
||||
|
||||
jmp_buf m_jmp_state;
|
||||
mem_block *m_pMem_blocks;
|
||||
int m_image_x_size;
|
||||
int m_image_y_size;
|
||||
jpeg_decoder_stream *m_pStream;
|
||||
int m_progressive_flag;
|
||||
uint8 m_huff_ac[JPGD_MAX_HUFF_TABLES];
|
||||
uint8* m_huff_num[JPGD_MAX_HUFF_TABLES]; // pointer to number of Huffman codes per bit size
|
||||
uint8* m_huff_val[JPGD_MAX_HUFF_TABLES]; // pointer to Huffman codes per bit size
|
||||
jpgd_quant_t* m_quant[JPGD_MAX_QUANT_TABLES]; // pointer to quantization tables
|
||||
int m_scan_type; // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no longer supported)
|
||||
int m_comps_in_frame; // # of components in frame
|
||||
int m_comp_h_samp[JPGD_MAX_COMPONENTS]; // component's horizontal sampling factor
|
||||
int m_comp_v_samp[JPGD_MAX_COMPONENTS]; // component's vertical sampling factor
|
||||
int m_comp_quant[JPGD_MAX_COMPONENTS]; // component's quantization table selector
|
||||
int m_comp_ident[JPGD_MAX_COMPONENTS]; // component's ID
|
||||
int m_comp_h_blocks[JPGD_MAX_COMPONENTS];
|
||||
int m_comp_v_blocks[JPGD_MAX_COMPONENTS];
|
||||
int m_comps_in_scan; // # of components in scan
|
||||
int m_comp_list[JPGD_MAX_COMPS_IN_SCAN]; // components in this scan
|
||||
int m_comp_dc_tab[JPGD_MAX_COMPONENTS]; // component's DC Huffman coding table selector
|
||||
int m_comp_ac_tab[JPGD_MAX_COMPONENTS]; // component's AC Huffman coding table selector
|
||||
int m_spectral_start; // spectral selection start
|
||||
int m_spectral_end; // spectral selection end
|
||||
int m_successive_low; // successive approximation low
|
||||
int m_successive_high; // successive approximation high
|
||||
int m_max_mcu_x_size; // MCU's max. X size in pixels
|
||||
int m_max_mcu_y_size; // MCU's max. Y size in pixels
|
||||
int m_blocks_per_mcu;
|
||||
int m_max_blocks_per_row;
|
||||
int m_mcus_per_row, m_mcus_per_col;
|
||||
int m_mcu_org[JPGD_MAX_BLOCKS_PER_MCU];
|
||||
int m_total_lines_left; // total # lines left in image
|
||||
int m_mcu_lines_left; // total # lines left in this MCU
|
||||
int m_real_dest_bytes_per_scan_line;
|
||||
int m_dest_bytes_per_scan_line; // rounded up
|
||||
int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y)
|
||||
huff_tables* m_pHuff_tabs[JPGD_MAX_HUFF_TABLES];
|
||||
coeff_buf* m_dc_coeffs[JPGD_MAX_COMPONENTS];
|
||||
coeff_buf* m_ac_coeffs[JPGD_MAX_COMPONENTS];
|
||||
int m_eob_run;
|
||||
int m_block_y_mcu[JPGD_MAX_COMPONENTS];
|
||||
uint8* m_pIn_buf_ofs;
|
||||
int m_in_buf_left;
|
||||
int m_tem_flag;
|
||||
bool m_eof_flag;
|
||||
uint8 m_in_buf_pad_start[128];
|
||||
uint8 m_in_buf[JPGD_IN_BUF_SIZE + 128];
|
||||
uint8 m_in_buf_pad_end[128];
|
||||
int m_bits_left;
|
||||
uint m_bit_buf;
|
||||
int m_restart_interval;
|
||||
int m_restarts_left;
|
||||
int m_next_restart_num;
|
||||
int m_max_mcus_per_row;
|
||||
int m_max_blocks_per_mcu;
|
||||
int m_expanded_blocks_per_mcu;
|
||||
int m_expanded_blocks_per_row;
|
||||
int m_expanded_blocks_per_component;
|
||||
bool m_freq_domain_chroma_upsample;
|
||||
int m_max_mcus_per_col;
|
||||
uint m_last_dc_val[JPGD_MAX_COMPONENTS];
|
||||
jpgd_block_t* m_pMCU_coefficients;
|
||||
int m_mcu_block_max_zag[JPGD_MAX_BLOCKS_PER_MCU];
|
||||
uint8* m_pSample_buf;
|
||||
int m_crr[256];
|
||||
int m_cbb[256];
|
||||
int m_crg[256];
|
||||
int m_cbg[256];
|
||||
uint8* m_pScan_line_0;
|
||||
uint8* m_pScan_line_1;
|
||||
jpgd_status m_error_code;
|
||||
bool m_ready_flag;
|
||||
int m_total_bytes_read;
|
||||
|
||||
void free_all_blocks();
|
||||
JPGD_NORETURN void stop_decoding(jpgd_status status);
|
||||
void *alloc(size_t n, bool zero = false);
|
||||
void word_clear(void *p, uint16 c, uint n);
|
||||
void prep_in_buffer();
|
||||
void read_dht_marker();
|
||||
void read_dqt_marker();
|
||||
void read_sof_marker();
|
||||
void skip_variable_marker();
|
||||
void read_dri_marker();
|
||||
void read_sos_marker();
|
||||
int next_marker();
|
||||
int process_markers();
|
||||
void locate_soi_marker();
|
||||
void locate_sof_marker();
|
||||
int locate_sos_marker();
|
||||
void init(jpeg_decoder_stream * pStream);
|
||||
void create_look_ups();
|
||||
void fix_in_buffer();
|
||||
void transform_mcu(int mcu_row);
|
||||
void transform_mcu_expand(int mcu_row);
|
||||
coeff_buf* coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y);
|
||||
inline jpgd_block_t *coeff_buf_getp(coeff_buf *cb, int block_x, int block_y);
|
||||
void load_next_row();
|
||||
void decode_next_row();
|
||||
void make_huff_table(int index, huff_tables *pH);
|
||||
void check_quant_tables();
|
||||
void check_huff_tables();
|
||||
void calc_mcu_block_order();
|
||||
int init_scan();
|
||||
void init_frame();
|
||||
void process_restart();
|
||||
void decode_scan(pDecode_block_func decode_block_func);
|
||||
void init_progressive();
|
||||
void init_sequential();
|
||||
void decode_start();
|
||||
void decode_init(jpeg_decoder_stream * pStream);
|
||||
void H2V2Convert();
|
||||
void H2V1Convert();
|
||||
void H1V2Convert();
|
||||
void H1V1Convert();
|
||||
void gray_convert();
|
||||
void expanded_convert();
|
||||
void find_eoi();
|
||||
inline uint get_char();
|
||||
inline uint get_char(bool *pPadding_flag);
|
||||
inline void stuff_char(uint8 q);
|
||||
inline uint8 get_octet();
|
||||
inline uint get_bits(int num_bits);
|
||||
inline uint get_bits_no_markers(int numbits);
|
||||
inline int huff_decode(huff_tables *pH);
|
||||
inline int huff_decode(huff_tables *pH, int& extrabits);
|
||||
static inline uint8 clamp(int i);
|
||||
static void decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y);
|
||||
static void decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y);
|
||||
static void decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y);
|
||||
static void decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y);
|
||||
};
|
||||
|
||||
} // namespace jpgd
|
||||
|
||||
#endif // JPEG_DECODER_H
|
|
@ -1,93 +0,0 @@
|
|||
/*************************************************/
|
||||
/* image_loader_jpg.cpp */
|
||||
/*************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/*************************************************/
|
||||
/* Source code within this file is: */
|
||||
/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
|
||||
/* All Rights Reserved. */
|
||||
/*************************************************/
|
||||
|
||||
#include "image_loader_jpg.h"
|
||||
|
||||
#include "print_string.h"
|
||||
#include "os/os.h"
|
||||
#include "drivers/jpg/tinyjpeg.h"
|
||||
|
||||
|
||||
static void* _tinyjpg_alloc(unsigned int amount) {
|
||||
|
||||
return memalloc(amount);
|
||||
}
|
||||
|
||||
static void _tinyjpg_free(void *ptr) {
|
||||
|
||||
memfree(ptr);
|
||||
}
|
||||
|
||||
Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) {
|
||||
|
||||
|
||||
DVector<uint8_t> src_image;
|
||||
int src_image_len = f->get_len();
|
||||
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
|
||||
src_image.resize(src_image_len);
|
||||
|
||||
DVector<uint8_t>::Write w = src_image.write();
|
||||
|
||||
f->get_buffer(&w[0],src_image_len);
|
||||
|
||||
f->close();
|
||||
|
||||
jdec_private* jdec=tinyjpeg_init(_tinyjpg_alloc,_tinyjpg_free);
|
||||
ERR_FAIL_COND_V(!jdec,ERR_UNAVAILABLE);
|
||||
|
||||
int ret = tinyjpeg_parse_header(jdec,&w[0],src_image_len);
|
||||
|
||||
if (ret!=0) {
|
||||
tinyjpeg_free(jdec);
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(ret!=0,ERR_FILE_CORRUPT);
|
||||
|
||||
unsigned int width,height;
|
||||
|
||||
|
||||
tinyjpeg_get_size(jdec,&width,&height);
|
||||
|
||||
|
||||
|
||||
DVector<uint8_t> imgdata;
|
||||
imgdata.resize(width*height*3);
|
||||
DVector<uint8_t>::Write imgdataw = imgdata.write();
|
||||
|
||||
|
||||
unsigned char *components[1]={&imgdataw[0]};
|
||||
tinyjpeg_set_components(jdec,components,1);
|
||||
tinyjpeg_decode(jdec,TINYJPEG_FMT_RGB24);
|
||||
imgdataw = DVector<uint8_t>::Write();
|
||||
|
||||
Image dst_image(width,height,0,Image::FORMAT_RGB,imgdata);
|
||||
|
||||
tinyjpeg_free(jdec);
|
||||
|
||||
*p_image=dst_image;
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const {
|
||||
|
||||
p_extensions->push_back("jpg");
|
||||
p_extensions->push_back("jpeg");
|
||||
}
|
||||
|
||||
|
||||
ImageLoaderJPG::ImageLoaderJPG() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,286 +0,0 @@
|
|||
/*
|
||||
* jidctflt.c
|
||||
*
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
*
|
||||
* The authors make NO WARRANTY or representation, either express or implied,
|
||||
* with respect to this software, its quality, accuracy, merchantability, or
|
||||
* fitness for a particular purpose. This software is provided "AS IS", and you,
|
||||
* its user, assume the entire risk as to its quality and accuracy.
|
||||
*
|
||||
* This software is copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* All Rights Reserved except as specified below.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify, and distribute this
|
||||
* software (or portions thereof) for any purpose, without fee, subject to these
|
||||
* conditions:
|
||||
* (1) If any part of the source code for this software is distributed, then this
|
||||
* README file must be included, with this copyright and no-warranty notice
|
||||
* unaltered; and any additions, deletions, or changes to the original files
|
||||
* must be clearly indicated in accompanying documentation.
|
||||
* (2) If only executable code is distributed, then the accompanying
|
||||
* documentation must state that "this software is based in part on the work of
|
||||
* the Independent JPEG Group".
|
||||
* (3) Permission for use of this software is granted only if the user accepts
|
||||
* full responsibility for any undesirable consequences; the authors accept
|
||||
* NO LIABILITY for damages of any kind.
|
||||
*
|
||||
* These conditions apply to any software derived from or based on the IJG code,
|
||||
* not just to the unmodified library. If you use our work, you ought to
|
||||
* acknowledge us.
|
||||
*
|
||||
* Permission is NOT granted for the use of any IJG author's name or company name
|
||||
* in advertising or publicity relating to this software or products derived from
|
||||
* it. This software may be referred to only as "the Independent JPEG Group's
|
||||
* software".
|
||||
*
|
||||
* We specifically permit and encourage the use of this software as the basis of
|
||||
* commercial products, provided that all warranty or liability claims are
|
||||
* assumed by the product vendor.
|
||||
*
|
||||
*
|
||||
* This file contains a floating-point implementation of the
|
||||
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
|
||||
* must also perform dequantization of the input coefficients.
|
||||
*
|
||||
* This implementation should be more accurate than either of the integer
|
||||
* IDCT implementations. However, it may not give the same results on all
|
||||
* machines because of differences in roundoff behavior. Speed will depend
|
||||
* on the hardware's floating point capacity.
|
||||
*
|
||||
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
|
||||
* on each row (or vice versa, but it's more convenient to emit a row at
|
||||
* a time). Direct algorithms are also available, but they are much more
|
||||
* complex and seem not to be any faster when reduced to code.
|
||||
*
|
||||
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
|
||||
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
|
||||
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
|
||||
* JPEG textbook (see REFERENCES section in file README). The following code
|
||||
* is based directly on figure 4-8 in P&M.
|
||||
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
|
||||
* possible to arrange the computation so that many of the multiplies are
|
||||
* simple scalings of the final outputs. These multiplies can then be
|
||||
* folded into the multiplications or divisions by the JPEG quantization
|
||||
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
|
||||
* to be done in the DCT itself.
|
||||
* The primary disadvantage of this method is that with a fixed-point
|
||||
* implementation, accuracy is lost due to imprecise representation of the
|
||||
* scaled quantization values. However, that problem does not arise if
|
||||
* we use floating point arithmetic.
|
||||
*/
|
||||
|
||||
#include "tinyjpeg-internal.h"
|
||||
|
||||
#define FAST_FLOAT float
|
||||
#define DCTSIZE 8
|
||||
#define DCTSIZE2 (DCTSIZE*DCTSIZE)
|
||||
|
||||
#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
|
||||
|
||||
#if 0 && defined(__GNUC__) && (defined(__i686__))
|
||||
// || defined(__x86_64__))
|
||||
|
||||
static inline unsigned char descale_and_clamp(int x, int shift)
|
||||
{
|
||||
__asm__ (
|
||||
"add %3,%1\n"
|
||||
"\tsar %2,%1\n"
|
||||
"\tsub $-128,%1\n"
|
||||
"\tcmovl %5,%1\n" /* Use the sub to compare to 0 */
|
||||
"\tcmpl %4,%1\n"
|
||||
"\tcmovg %4,%1\n"
|
||||
: "=r"(x)
|
||||
: "0"(x), "Ir"(shift), "ir"(1UL<<(shift-1)), "r" (0xff), "r" (0)
|
||||
);
|
||||
return x;
|
||||
}
|
||||
|
||||
#else
|
||||
static __inline unsigned char descale_and_clamp(int x, int shift)
|
||||
{
|
||||
x += (1UL<<(shift-1));
|
||||
if (x<0)
|
||||
x = (x >> shift) | ((~(0UL)) << (32-(shift)));
|
||||
else
|
||||
x >>= shift;
|
||||
x += 128;
|
||||
if (x>255)
|
||||
return 255;
|
||||
else if (x<0)
|
||||
return 0;
|
||||
else
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Perform dequantization and inverse DCT on one block of coefficients.
|
||||
*/
|
||||
|
||||
void
|
||||
tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride)
|
||||
{
|
||||
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
|
||||
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
|
||||
FAST_FLOAT z5, z10, z11, z12, z13;
|
||||
int16_t *inptr;
|
||||
FAST_FLOAT *quantptr;
|
||||
FAST_FLOAT *wsptr;
|
||||
uint8_t *outptr;
|
||||
int ctr;
|
||||
FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
|
||||
|
||||
/* Pass 1: process columns from input, store into work array. */
|
||||
|
||||
inptr = compptr->DCT;
|
||||
quantptr = compptr->Q_table;
|
||||
wsptr = workspace;
|
||||
for (ctr = DCTSIZE; ctr > 0; ctr--) {
|
||||
/* Due to quantization, we will usually find that many of the input
|
||||
* coefficients are zero, especially the AC terms. We can exploit this
|
||||
* by short-circuiting the IDCT calculation for any column in which all
|
||||
* the AC terms are zero. In that case each output is equal to the
|
||||
* DC coefficient (with scale factor as needed).
|
||||
* With typical images and quantization tables, half or more of the
|
||||
* column DCT calculations can be simplified this way.
|
||||
*/
|
||||
|
||||
if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
|
||||
inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
|
||||
inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
|
||||
inptr[DCTSIZE*7] == 0) {
|
||||
/* AC terms all zero */
|
||||
FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
|
||||
|
||||
wsptr[DCTSIZE*0] = dcval;
|
||||
wsptr[DCTSIZE*1] = dcval;
|
||||
wsptr[DCTSIZE*2] = dcval;
|
||||
wsptr[DCTSIZE*3] = dcval;
|
||||
wsptr[DCTSIZE*4] = dcval;
|
||||
wsptr[DCTSIZE*5] = dcval;
|
||||
wsptr[DCTSIZE*6] = dcval;
|
||||
wsptr[DCTSIZE*7] = dcval;
|
||||
|
||||
inptr++; /* advance pointers to next column */
|
||||
quantptr++;
|
||||
wsptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Even part */
|
||||
|
||||
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
|
||||
tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
|
||||
tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
|
||||
tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
|
||||
|
||||
tmp10 = tmp0 + tmp2; /* phase 3 */
|
||||
tmp11 = tmp0 - tmp2;
|
||||
|
||||
tmp13 = tmp1 + tmp3; /* phases 5-3 */
|
||||
tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
|
||||
|
||||
tmp0 = tmp10 + tmp13; /* phase 2 */
|
||||
tmp3 = tmp10 - tmp13;
|
||||
tmp1 = tmp11 + tmp12;
|
||||
tmp2 = tmp11 - tmp12;
|
||||
|
||||
/* Odd part */
|
||||
|
||||
tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
|
||||
tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
|
||||
tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
|
||||
tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
|
||||
|
||||
z13 = tmp6 + tmp5; /* phase 6 */
|
||||
z10 = tmp6 - tmp5;
|
||||
z11 = tmp4 + tmp7;
|
||||
z12 = tmp4 - tmp7;
|
||||
|
||||
tmp7 = z11 + z13; /* phase 5 */
|
||||
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
|
||||
|
||||
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
|
||||
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
|
||||
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
|
||||
|
||||
tmp6 = tmp12 - tmp7; /* phase 2 */
|
||||
tmp5 = tmp11 - tmp6;
|
||||
tmp4 = tmp10 + tmp5;
|
||||
|
||||
wsptr[DCTSIZE*0] = tmp0 + tmp7;
|
||||
wsptr[DCTSIZE*7] = tmp0 - tmp7;
|
||||
wsptr[DCTSIZE*1] = tmp1 + tmp6;
|
||||
wsptr[DCTSIZE*6] = tmp1 - tmp6;
|
||||
wsptr[DCTSIZE*2] = tmp2 + tmp5;
|
||||
wsptr[DCTSIZE*5] = tmp2 - tmp5;
|
||||
wsptr[DCTSIZE*4] = tmp3 + tmp4;
|
||||
wsptr[DCTSIZE*3] = tmp3 - tmp4;
|
||||
|
||||
inptr++; /* advance pointers to next column */
|
||||
quantptr++;
|
||||
wsptr++;
|
||||
}
|
||||
|
||||
/* Pass 2: process rows from work array, store into output array. */
|
||||
/* Note that we must descale the results by a factor of 8 == 2**3. */
|
||||
|
||||
wsptr = workspace;
|
||||
outptr = output_buf;
|
||||
for (ctr = 0; ctr < DCTSIZE; ctr++) {
|
||||
/* Rows of zeroes can be exploited in the same way as we did with columns.
|
||||
* However, the column calculation has created many nonzero AC terms, so
|
||||
* the simplification applies less often (typically 5% to 10% of the time).
|
||||
* And testing floats for zero is relatively expensive, so we don't bother.
|
||||
*/
|
||||
|
||||
/* Even part */
|
||||
|
||||
tmp10 = wsptr[0] + wsptr[4];
|
||||
tmp11 = wsptr[0] - wsptr[4];
|
||||
|
||||
tmp13 = wsptr[2] + wsptr[6];
|
||||
tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
|
||||
|
||||
tmp0 = tmp10 + tmp13;
|
||||
tmp3 = tmp10 - tmp13;
|
||||
tmp1 = tmp11 + tmp12;
|
||||
tmp2 = tmp11 - tmp12;
|
||||
|
||||
/* Odd part */
|
||||
|
||||
z13 = wsptr[5] + wsptr[3];
|
||||
z10 = wsptr[5] - wsptr[3];
|
||||
z11 = wsptr[1] + wsptr[7];
|
||||
z12 = wsptr[1] - wsptr[7];
|
||||
|
||||
tmp7 = z11 + z13;
|
||||
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
|
||||
|
||||
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
|
||||
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
|
||||
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
|
||||
|
||||
tmp6 = tmp12 - tmp7;
|
||||
tmp5 = tmp11 - tmp6;
|
||||
tmp4 = tmp10 + tmp5;
|
||||
|
||||
/* Final output stage: scale down by a factor of 8 and range-limit */
|
||||
|
||||
outptr[0] = descale_and_clamp((int)(tmp0 + tmp7), 3);
|
||||
outptr[7] = descale_and_clamp((int)(tmp0 - tmp7), 3);
|
||||
outptr[1] = descale_and_clamp((int)(tmp1 + tmp6), 3);
|
||||
outptr[6] = descale_and_clamp((int)(tmp1 - tmp6), 3);
|
||||
outptr[2] = descale_and_clamp((int)(tmp2 + tmp5), 3);
|
||||
outptr[5] = descale_and_clamp((int)(tmp2 - tmp5), 3);
|
||||
outptr[4] = descale_and_clamp((int)(tmp3 + tmp4), 3);
|
||||
outptr[3] = descale_and_clamp((int)(tmp3 - tmp4), 3);
|
||||
|
||||
|
||||
wsptr += DCTSIZE; /* advance pointer to next row */
|
||||
outptr += stride;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,341 +0,0 @@
|
|||
/*
|
||||
* Small jpeg decoder library - testing application
|
||||
*
|
||||
* Copyright (c) 2006, Luc Saillard <luc@saillard.org>
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the author nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tinyjpeg.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define snprintf(buf, size, fmt, ...) sprintf(buf, fmt, __VA_ARGS__)
|
||||
|
||||
static void exitmessage(const char *message) __attribute__((noreturn));
|
||||
static void exitmessage(const char *message)
|
||||
{
|
||||
printf("%s\n", message);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int filesize(FILE *fp)
|
||||
{
|
||||
long pos;
|
||||
fseek(fp, 0, SEEK_END);
|
||||
pos = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a buffer in 24bits Targa format
|
||||
* (BGR byte order)
|
||||
*/
|
||||
static void write_tga(const char *filename, int output_format, int width, int height, unsigned char **components)
|
||||
{
|
||||
unsigned char targaheader[18];
|
||||
FILE *F;
|
||||
char temp[1024];
|
||||
unsigned int bufferlen = width * height * 3;
|
||||
unsigned char *rgb_data = components[0];
|
||||
|
||||
sprintf(temp, sizeof(temp), filename);
|
||||
|
||||
memset(targaheader,0,sizeof(targaheader));
|
||||
|
||||
targaheader[12] = (unsigned char) (width & 0xFF);
|
||||
targaheader[13] = (unsigned char) (width >> 8);
|
||||
targaheader[14] = (unsigned char) (height & 0xFF);
|
||||
targaheader[15] = (unsigned char) (height >> 8);
|
||||
targaheader[17] = 0x20; /* Top-down, non-interlaced */
|
||||
targaheader[2] = 2; /* image type = uncompressed RGB */
|
||||
targaheader[16] = 24;
|
||||
|
||||
if (output_format == TINYJPEG_FMT_RGB24)
|
||||
{
|
||||
unsigned char *data = rgb_data + bufferlen - 3;
|
||||
do
|
||||
{
|
||||
unsigned char c = data[0];
|
||||
data[0] = data[2];
|
||||
data[2] = c;
|
||||
data-=3;
|
||||
}
|
||||
while (data > rgb_data);
|
||||
}
|
||||
|
||||
F = fopen(temp, "wb");
|
||||
fwrite(targaheader, sizeof(targaheader), 1, F);
|
||||
fwrite(rgb_data, 1, bufferlen, F);
|
||||
fclose(F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a buffer in three files (.Y, .U, .V) useable by yuvsplittoppm
|
||||
*/
|
||||
static void write_yuv(const char *filename, int width, int height, unsigned char **components)
|
||||
{
|
||||
FILE *F;
|
||||
char temp[1024];
|
||||
|
||||
snprintf(temp, 1024, "%s.Y", filename);
|
||||
F = fopen(temp, "wb");
|
||||
fwrite(components[0], width, height, F);
|
||||
fclose(F);
|
||||
snprintf(temp, 1024, "%s.U", filename);
|
||||
F = fopen(temp, "wb");
|
||||
fwrite(components[1], width*height/4, 1, F);
|
||||
fclose(F);
|
||||
snprintf(temp, 1024, "%s.V", filename);
|
||||
F = fopen(temp, "wb");
|
||||
fwrite(components[2], width*height/4, 1, F);
|
||||
fclose(F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a buffer in grey image (pgm format)
|
||||
*/
|
||||
static void write_pgm(const char *filename, int width, int height, unsigned char **components)
|
||||
{
|
||||
FILE *F;
|
||||
char temp[1024];
|
||||
|
||||
snprintf(temp, 1024, "%s", filename);
|
||||
F = fopen(temp, "wb");
|
||||
fprintf(F, "P5\n%d %d\n255\n", width, height);
|
||||
fwrite(components[0], width, height, F);
|
||||
fclose(F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load one jpeg image, and try to decompress 1000 times, and save the result.
|
||||
* This is mainly used for benchmarking the decoder, or to test if between each
|
||||
* called of the library the DCT is corrected reset (a bug was found).
|
||||
*/
|
||||
int load_multiple_times(const char *filename, const char *outfilename, int output_format)
|
||||
{
|
||||
FILE *fp;
|
||||
int count, length_of_file;
|
||||
unsigned int width, height;
|
||||
unsigned char *buf;
|
||||
struct jdec_private *jdec;
|
||||
unsigned char *components[4];
|
||||
|
||||
jdec = tinyjpeg_init();
|
||||
count = 0;
|
||||
|
||||
/* Load the Jpeg into memory */
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == NULL)
|
||||
exitmessage("Cannot open filename\n");
|
||||
length_of_file = filesize(fp);
|
||||
buf = (unsigned char *)malloc(length_of_file + 4);
|
||||
fread(buf, length_of_file, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
while (count<1000)
|
||||
{
|
||||
if (tinyjpeg_parse_header(jdec, buf, length_of_file)<0)
|
||||
exitmessage(tinyjpeg_get_errorstring(jdec));
|
||||
|
||||
tinyjpeg_decode(jdec, output_format);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get address for each plane (not only max 3 planes is supported), and
|
||||
* depending of the output mode, only some components will be filled
|
||||
* RGB: 1 plane, YUV420P: 3 planes, GREY: 1 plane
|
||||
*/
|
||||
tinyjpeg_get_components(jdec, components);
|
||||
tinyjpeg_get_size(jdec, &width, &height);
|
||||
|
||||
/* Save it */
|
||||
switch (output_format)
|
||||
{
|
||||
case TINYJPEG_FMT_RGB24:
|
||||
case TINYJPEG_FMT_BGR24:
|
||||
write_tga(outfilename, output_format, width, height, components);
|
||||
break;
|
||||
case TINYJPEG_FMT_YUV420P:
|
||||
write_yuv(outfilename, width, height, components);
|
||||
break;
|
||||
case TINYJPEG_FMT_GREY:
|
||||
write_pgm(outfilename, width, height, components);
|
||||
break;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
tinyjpeg_free(jdec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load one jpeg image, and decompress it, and save the result.
|
||||
*/
|
||||
int convert_one_image(const char *infilename, const char *outfilename, int output_format)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned int length_of_file;
|
||||
unsigned int width, height;
|
||||
unsigned char *buf;
|
||||
struct jdec_private *jdec;
|
||||
unsigned char *components[3];
|
||||
|
||||
/* Load the Jpeg into memory */
|
||||
fp = fopen(infilename, "rb");
|
||||
if (fp == NULL)
|
||||
exitmessage("Cannot open filename\n");
|
||||
length_of_file = filesize(fp);
|
||||
buf = (unsigned char *)malloc(length_of_file + 4);
|
||||
if (buf == NULL)
|
||||
exitmessage("Not enough memory for loading file\n");
|
||||
fread(buf, length_of_file, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
/* Decompress it */
|
||||
jdec = tinyjpeg_init();
|
||||
if (jdec == NULL)
|
||||
exitmessage("Not enough memory to alloc the structure need for decompressing\n");
|
||||
|
||||
if (tinyjpeg_parse_header(jdec, buf, length_of_file)<0)
|
||||
exitmessage(tinyjpeg_get_errorstring(jdec));
|
||||
|
||||
/* Get the size of the image */
|
||||
tinyjpeg_get_size(jdec, &width, &height);
|
||||
|
||||
printf("Decoding JPEG image...\n");
|
||||
if (tinyjpeg_decode(jdec, output_format) < 0)
|
||||
exitmessage(tinyjpeg_get_errorstring(jdec));
|
||||
|
||||
/*
|
||||
* Get address for each plane (not only max 3 planes is supported), and
|
||||
* depending of the output mode, only some components will be filled
|
||||
* RGB: 1 plane, YUV420P: 3 planes, GREY: 1 plane
|
||||
*/
|
||||
tinyjpeg_get_components(jdec, components);
|
||||
|
||||
/* Save it */
|
||||
switch (output_format)
|
||||
{
|
||||
case TINYJPEG_FMT_RGB24:
|
||||
case TINYJPEG_FMT_BGR24:
|
||||
write_tga(outfilename, output_format, width, height, components);
|
||||
break;
|
||||
case TINYJPEG_FMT_YUV420P:
|
||||
write_yuv(outfilename, width, height, components);
|
||||
break;
|
||||
case TINYJPEG_FMT_GREY:
|
||||
write_pgm(outfilename, width, height, components);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Only called this if the buffers were allocated by tinyjpeg_decode() */
|
||||
tinyjpeg_free(jdec);
|
||||
/* else called just free(jdec); */
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: loadjpeg [options] <input_filename.jpeg> <format> <output_filename>\n");
|
||||
fprintf(stderr, "options:\n");
|
||||
fprintf(stderr, " --benchmark - Convert 1000 times the same image\n");
|
||||
fprintf(stderr, "format:\n");
|
||||
fprintf(stderr, " yuv420p - output 3 files .Y,.U,.V\n");
|
||||
fprintf(stderr, " rgb24 - output a .tga image\n");
|
||||
fprintf(stderr, " bgr24 - output a .tga image\n");
|
||||
fprintf(stderr, " gray - output a .pgm image\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* main
|
||||
*
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int output_format = TINYJPEG_FMT_YUV420P;
|
||||
char *output_filename, *input_filename;
|
||||
clock_t start_time, finish_time;
|
||||
unsigned int duration;
|
||||
int current_argument;
|
||||
int benchmark_mode = 0;
|
||||
|
||||
if (argc < 3)
|
||||
usage();
|
||||
|
||||
current_argument = 1;
|
||||
while (1)
|
||||
{
|
||||
if (strcmp(argv[current_argument], "--benchmark")==0)
|
||||
benchmark_mode = 1;
|
||||
else
|
||||
break;
|
||||
current_argument++;
|
||||
}
|
||||
|
||||
if (argc < current_argument+2)
|
||||
usage();
|
||||
|
||||
input_filename = argv[current_argument];
|
||||
if (strcmp(argv[current_argument+1],"yuv420p")==0)
|
||||
output_format = TINYJPEG_FMT_YUV420P;
|
||||
else if (strcmp(argv[current_argument+1],"rgb24")==0)
|
||||
output_format = TINYJPEG_FMT_RGB24;
|
||||
else if (strcmp(argv[current_argument+1],"bgr24")==0)
|
||||
output_format = TINYJPEG_FMT_BGR24;
|
||||
else if (strcmp(argv[current_argument+1],"grey")==0)
|
||||
output_format = TINYJPEG_FMT_GREY;
|
||||
else
|
||||
exitmessage("Bad format: need to be one of yuv420p, rgb24, bgr24, grey\n");
|
||||
output_filename = argv[current_argument+2];
|
||||
|
||||
start_time = clock();
|
||||
|
||||
if (benchmark_mode)
|
||||
load_multiple_times(input_filename, output_filename, output_format);
|
||||
else
|
||||
convert_one_image(input_filename, output_filename, output_format);
|
||||
|
||||
finish_time = clock();
|
||||
duration = finish_time - start_time;
|
||||
printf("Decoding finished in %u ticks\n", duration);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* Small jpeg decoder library (Internal header)
|
||||
*
|
||||
* Copyright (c) 2006, Luc Saillard <luc@saillard.org>
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the author nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TINYJPEG_INTERNAL_H_
|
||||
#define __TINYJPEG_INTERNAL_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef NO_STDINT_H
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed int int32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long int64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#define SANITY_CHECK 1
|
||||
|
||||
struct jdec_private;
|
||||
|
||||
#define HUFFMAN_BITS_SIZE 256
|
||||
#define HUFFMAN_HASH_NBITS 9
|
||||
#define HUFFMAN_HASH_SIZE (1UL<<HUFFMAN_HASH_NBITS)
|
||||
#define HUFFMAN_HASH_MASK (HUFFMAN_HASH_SIZE-1)
|
||||
|
||||
#define HUFFMAN_TABLES 4
|
||||
#define COMPONENTS 3
|
||||
#define JPEG_MAX_WIDTH 4096
|
||||
#define JPEG_MAX_HEIGHT 4096
|
||||
|
||||
struct huffman_table
|
||||
{
|
||||
/* Fast look up table, using HUFFMAN_HASH_NBITS bits we can have directly the symbol,
|
||||
* if the symbol is <0, then we need to look into the tree table */
|
||||
short int lookup[HUFFMAN_HASH_SIZE];
|
||||
/* code size: give the number of bits of a symbol is encoded */
|
||||
unsigned char code_size[HUFFMAN_HASH_SIZE];
|
||||
/* some place to store value that is not encoded in the lookup table
|
||||
* FIXME: Calculate if 256 value is enough to store all values
|
||||
*/
|
||||
uint16_t slowtable[16-HUFFMAN_HASH_NBITS][256];
|
||||
};
|
||||
|
||||
struct component
|
||||
{
|
||||
unsigned int Hfactor;
|
||||
unsigned int Vfactor;
|
||||
float *Q_table; /* Pointer to the quantisation table to use */
|
||||
struct huffman_table *AC_table;
|
||||
struct huffman_table *DC_table;
|
||||
short int previous_DC; /* Previous DC coefficient */
|
||||
short int DCT[64]; /* DCT coef */
|
||||
#if SANITY_CHECK
|
||||
unsigned int cid;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef void (*decode_MCU_fct) (struct jdec_private *priv);
|
||||
typedef void (*convert_colorspace_fct) (struct jdec_private *priv);
|
||||
|
||||
struct jdec_private
|
||||
{
|
||||
void *(*allocate_mem)(unsigned int amount);
|
||||
void (*free_mem)(void *mem);
|
||||
|
||||
/* Public variables */
|
||||
uint8_t *components[COMPONENTS];
|
||||
unsigned int width, height; /* Size of the image */
|
||||
unsigned int flags;
|
||||
|
||||
/* Private variables */
|
||||
const unsigned char *stream_begin, *stream_end;
|
||||
unsigned int stream_length;
|
||||
|
||||
const unsigned char *stream; /* Pointer to the current stream */
|
||||
unsigned int reservoir, nbits_in_reservoir;
|
||||
|
||||
struct component component_infos[COMPONENTS];
|
||||
float Q_tables[COMPONENTS][64]; /* quantization tables */
|
||||
struct huffman_table HTDC[HUFFMAN_TABLES]; /* DC huffman tables */
|
||||
struct huffman_table HTAC[HUFFMAN_TABLES]; /* AC huffman tables */
|
||||
int default_huffman_table_initialized;
|
||||
int restart_interval;
|
||||
int restarts_to_go; /* MCUs left in this restart interval */
|
||||
int last_rst_marker_seen; /* Rst marker is incremented each time */
|
||||
|
||||
/* Temp space used after the IDCT to store each components */
|
||||
uint8_t Y[64*4], Cr[64], Cb[64];
|
||||
|
||||
jmp_buf jump_state;
|
||||
/* Internal Pointer use for colorspace conversion, do not modify it !!! */
|
||||
uint8_t *plane[COMPONENTS];
|
||||
|
||||
uint8_t decomp_block[16][16*3];
|
||||
|
||||
};
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3) && defined(__OPTIMIZE__)
|
||||
#define __likely(x) __builtin_expect(!!(x), 1)
|
||||
#define __unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
#define __likely(x) (x)
|
||||
#define __unlikely(x) (x)
|
||||
#endif
|
||||
|
||||
#define IDCT tinyjpeg_idct_float
|
||||
void tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Small jpeg decoder library (header file)
|
||||
*
|
||||
* Copyright (c) 2006, Luc Saillard <luc@saillard.org>
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the author nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __JPEGDEC_H__
|
||||
#define __JPEGDEC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct jdec_private;
|
||||
|
||||
/* Flags that can be set by any applications */
|
||||
#define TINYJPEG_FLAGS_MJPEG_TABLE (1<<1)
|
||||
|
||||
/* Format accepted in outout */
|
||||
enum tinyjpeg_fmt {
|
||||
TINYJPEG_FMT_GREY = 1,
|
||||
TINYJPEG_FMT_BGR24,
|
||||
TINYJPEG_FMT_RGB24,
|
||||
TINYJPEG_FMT_YUV420P,
|
||||
};
|
||||
|
||||
struct jdec_private *tinyjpeg_init(void *(*allocate_mem)(unsigned int),void (*free_mem)(void *));
|
||||
|
||||
void tinyjpeg_free(struct jdec_private *priv);
|
||||
|
||||
int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size);
|
||||
int tinyjpeg_decode(struct jdec_private *priv, int pixel_format);
|
||||
const char *tinyjpeg_get_errorstring(struct jdec_private *priv);
|
||||
void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height);
|
||||
int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components);
|
||||
int tinyjpeg_set_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents);
|
||||
int tinyjpeg_set_flags(struct jdec_private *priv, int flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Import('env')
|
||||
|
||||
|
||||
pnm_sources = [
|
||||
"pnm/bitmap_loader_pnm.cpp"
|
||||
]
|
||||
|
||||
env.drivers_sources+=pnm_sources
|
||||
|
||||
#env.add_source_files(env.drivers_sources, pnm_sources)
|
|
@ -0,0 +1,232 @@
|
|||
/*************************************************/
|
||||
/* image_loader_jpg.cpp */
|
||||
/*************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/*************************************************/
|
||||
/* Source code within this file is: */
|
||||
/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
|
||||
/* All Rights Reserved. */
|
||||
/*************************************************/
|
||||
|
||||
#include "bitmap_loader_pnm.h"
|
||||
#include "os/file_access.h"
|
||||
#include "scene/resources/bit_mask.h"
|
||||
|
||||
|
||||
static bool _get_token(FileAccessRef& f,uint8_t &saved,DVector<uint8_t>& r_token,bool p_binary=false,bool p_single_chunk=false) {
|
||||
|
||||
|
||||
int token_max = r_token.size();
|
||||
DVector<uint8_t>::Write w;
|
||||
if (token_max)
|
||||
w=r_token.write();
|
||||
int ofs=0;
|
||||
bool lf=false;
|
||||
|
||||
|
||||
while(true) {
|
||||
|
||||
uint8_t b;
|
||||
if (saved) {
|
||||
b=saved;
|
||||
saved=0;
|
||||
} else {
|
||||
b = f->get_8();
|
||||
}
|
||||
if (f->eof_reached()) {
|
||||
if (ofs) {
|
||||
w=DVector<uint8_t>::Write();
|
||||
r_token.resize(ofs);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ofs && !p_binary && b=='#') {
|
||||
//skip comment
|
||||
while(b!='\n') {
|
||||
if (f->eof_reached()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
b = f->get_8();
|
||||
}
|
||||
|
||||
lf=true;
|
||||
|
||||
} else if (b<=32 && !(p_binary && (ofs || lf))) {
|
||||
|
||||
if (b=='\n') {
|
||||
lf=true;
|
||||
}
|
||||
|
||||
|
||||
if (ofs && !p_single_chunk) {
|
||||
w=DVector<uint8_t>::Write();
|
||||
r_token.resize(ofs);
|
||||
saved=b;
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
||||
bool resized=false;
|
||||
while (ofs>=token_max) {
|
||||
if (token_max)
|
||||
token_max<<=1;
|
||||
else
|
||||
token_max=1;
|
||||
resized=true;
|
||||
}
|
||||
if (resized) {
|
||||
w=DVector<uint8_t>::Write();
|
||||
r_token.resize(token_max);
|
||||
w=r_token.write();
|
||||
}
|
||||
w[ofs++]=b;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int _get_number_from_token(DVector<uint8_t>& r_token) {
|
||||
|
||||
int len = r_token.size();
|
||||
DVector<uint8_t>::Read r = r_token.read();
|
||||
return String::to_int((const char*)r.ptr(),len);
|
||||
|
||||
}
|
||||
|
||||
|
||||
RES ResourceFormatPBM::load(const String &p_path,const String& p_original_path,Error *r_error) {
|
||||
|
||||
#define _RETURN(m_err)\
|
||||
{\
|
||||
if (r_error)\
|
||||
*r_error=m_err;\
|
||||
ERR_FAIL_V(RES());\
|
||||
}
|
||||
|
||||
|
||||
FileAccessRef f=FileAccess::open(p_path,FileAccess::READ);
|
||||
uint8_t saved=0;
|
||||
if (!f)
|
||||
_RETURN(ERR_CANT_OPEN);
|
||||
|
||||
DVector<uint8_t> token;
|
||||
|
||||
if (!_get_token(f,saved,token)) {
|
||||
_RETURN(ERR_PARSE_ERROR);
|
||||
}
|
||||
|
||||
if (token.size()!=2) {
|
||||
_RETURN(ERR_FILE_CORRUPT);
|
||||
}
|
||||
if (token[0]!='P') {
|
||||
_RETURN(ERR_FILE_CORRUPT);
|
||||
}
|
||||
if (token[1]!='1' && token[1]!='4') {
|
||||
_RETURN(ERR_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
bool bits = token[1]=='4';
|
||||
|
||||
if (!_get_token(f,saved,token)) {
|
||||
_RETURN(ERR_PARSE_ERROR);
|
||||
}
|
||||
|
||||
int width = _get_number_from_token(token);
|
||||
if (width<=0) {
|
||||
_RETURN(ERR_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
|
||||
if (!_get_token(f,saved,token)) {
|
||||
_RETURN(ERR_PARSE_ERROR);
|
||||
}
|
||||
|
||||
int height = _get_number_from_token(token);
|
||||
if (height<=0) {
|
||||
_RETURN(ERR_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
|
||||
Ref<BitMap> bm;
|
||||
bm.instance();
|
||||
bm->create(Size2i(width,height));
|
||||
|
||||
if (!bits) {
|
||||
|
||||
int required_bytes = width*height;
|
||||
if (!_get_token(f,saved,token,false,true)) {
|
||||
_RETURN(ERR_PARSE_ERROR);
|
||||
}
|
||||
|
||||
if (token.size()<required_bytes) {
|
||||
_RETURN(ERR_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
DVector<uint8_t>::Read r=token.read();
|
||||
|
||||
for(int i=0;i<height;i++) {
|
||||
for(int j=0;j<width;j++) {
|
||||
|
||||
|
||||
char num = r[i*width+j];
|
||||
bm->set_bit(Point2i(j,i),num=='0');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
//a single, entire token of bits!
|
||||
if (!_get_token(f,saved,token,true)) {
|
||||
_RETURN(ERR_PARSE_ERROR);
|
||||
}
|
||||
int required_bytes = Math::ceil((width*height)/8.0);
|
||||
if (token.size()<required_bytes) {
|
||||
_RETURN(ERR_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
DVector<uint8_t>::Read r=token.read();
|
||||
|
||||
for(int i=0;i<height;i++) {
|
||||
for(int j=0;j<width;j++) {
|
||||
|
||||
int ofs = width*i+j;
|
||||
|
||||
uint8_t byte = r[ofs/8];
|
||||
bool bit = (byte>>(7-(ofs%8)))&1;
|
||||
|
||||
bm->set_bit(Point2i(j,i),!bit);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bm;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ResourceFormatPBM::get_recognized_extensions(List<String> *p_extensions) const {
|
||||
p_extensions->push_back("pbm");
|
||||
}
|
||||
bool ResourceFormatPBM::handles_type(const String& p_type) const {
|
||||
return p_type=="BitMap";
|
||||
}
|
||||
String ResourceFormatPBM::get_resource_type(const String &p_path) const {
|
||||
|
||||
if (p_path.extension().to_lower()=="pbm")
|
||||
return "BitMap";
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*************************************************/
|
||||
/* image_loader_jpg.h */
|
||||
/*************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/*************************************************/
|
||||
/* Source code within this file is: */
|
||||
/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
|
||||
/* All Rights Reserved. */
|
||||
/*************************************************/
|
||||
|
||||
#ifndef BITMAP_LOADER_PNM_H
|
||||
#define BITMAP_LOADER_PNM_H
|
||||
|
||||
#include "io/resource_loader.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class ResourceFormatPBM : public ResourceFormatLoader {
|
||||
|
||||
|
||||
public:
|
||||
|
||||
virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
|
||||
virtual void get_recognized_extensions(List<String> *p_extensions) const;
|
||||
virtual bool handles_type(const String& p_type) const;
|
||||
virtual String get_resource_type(const String &p_path) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -14,11 +14,12 @@
|
|||
#include "png/image_loader_png.h"
|
||||
#include "webp/image_loader_webp.h"
|
||||
#include "png/resource_saver_png.h"
|
||||
#include "jpg/image_loader_jpg.h"
|
||||
#include "jpegd/image_loader_jpegd.h"
|
||||
#include "dds/texture_loader_dds.h"
|
||||
#include "pvr/texture_loader_pvr.h"
|
||||
#include "etc1/image_etc.h"
|
||||
#include "chibi/event_stream_chibi.h"
|
||||
#include "pnm/bitmap_loader_pnm.h"
|
||||
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
@ -112,6 +113,9 @@ static ResourceFormatLoaderAudioStreamMPC * mpc_stream_loader=NULL;
|
|||
#include "openssl/register_openssl.h"
|
||||
#endif
|
||||
|
||||
|
||||
static ResourceFormatPBM * pbm_loader=NULL;
|
||||
|
||||
void register_core_driver_types() {
|
||||
|
||||
#ifdef PNG_ENABLED
|
||||
|
@ -138,6 +142,9 @@ void register_core_driver_types() {
|
|||
ImageLoader::add_image_format_loader( image_loader_jpg );
|
||||
#endif
|
||||
|
||||
pbm_loader = memnew( ResourceFormatPBM );
|
||||
ResourceLoader::add_resource_format_loader(pbm_loader);
|
||||
|
||||
ObjectTypeDB::register_type<RegEx>();
|
||||
}
|
||||
|
||||
|
@ -162,6 +169,7 @@ void unregister_core_driver_types() {
|
|||
memdelete( image_loader_jpg );
|
||||
#endif
|
||||
|
||||
memdelete( pbm_loader );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@
|
|||
|
||||
static ResourceFormatLoaderImage *resource_loader_image=NULL;
|
||||
static ResourceFormatLoaderWAV *resource_loader_wav=NULL;
|
||||
static ResourceFormatLoaderBitMap *resource_loader_bitmap=NULL;
|
||||
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
|
@ -249,8 +249,6 @@ void register_scene_types() {
|
|||
resource_loader_wav = memnew( ResourceFormatLoaderWAV );
|
||||
ResourceLoader::add_resource_format_loader( resource_loader_wav );
|
||||
|
||||
resource_loader_bitmap = memnew( ResourceFormatLoaderBitMap );
|
||||
ResourceLoader::add_resource_format_loader( resource_loader_bitmap );
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
|
@ -631,7 +629,6 @@ void unregister_scene_types() {
|
|||
|
||||
memdelete( resource_loader_image );
|
||||
memdelete( resource_loader_wav );
|
||||
memdelete( resource_loader_bitmap );
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
|
||||
|
|
|
@ -204,57 +204,3 @@ BitMap::BitMap() {
|
|||
|
||||
//////////////////////////////////////
|
||||
|
||||
|
||||
RES ResourceFormatLoaderBitMap::load(const String &p_path, const String& p_original_path, Error *r_error) {
|
||||
|
||||
if (r_error)
|
||||
*r_error=ERR_FILE_CANT_OPEN;
|
||||
|
||||
BitMap* ptr = memnew(BitMap);
|
||||
Ref<BitMap> bitmap( ptr );
|
||||
|
||||
|
||||
Image image;
|
||||
|
||||
Error err = ImageLoader::load_image(p_path,&image);
|
||||
|
||||
ERR_EXPLAIN("Failed loading image for BitMap: "+p_path);
|
||||
ERR_FAIL_COND_V(err, RES());
|
||||
|
||||
bitmap->create_from_image_alpha(image);
|
||||
if (r_error)
|
||||
*r_error=OK;
|
||||
|
||||
return bitmap;
|
||||
|
||||
}
|
||||
|
||||
bool ResourceFormatLoaderBitMap::handles_type(const String& p_type) const {
|
||||
|
||||
return (p_type=="BitMap");
|
||||
}
|
||||
|
||||
void ResourceFormatLoaderBitMap::get_recognized_extensions(List<String> *p_extensions) const {
|
||||
|
||||
ImageLoader::get_recognized_extensions(p_extensions);
|
||||
}
|
||||
|
||||
String ResourceFormatLoaderBitMap::get_resource_type(const String &p_path) const {
|
||||
|
||||
List<String> extensions;
|
||||
ImageLoader::get_recognized_extensions(&extensions);
|
||||
String ext=p_path.extension().to_lower();
|
||||
for(List<String>::Element *E=extensions.front();E;E=E->next()) {
|
||||
if (E->get()==ext)
|
||||
return "BitMap";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
ResourceFormatLoaderBitMap::ResourceFormatLoaderBitMap() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -62,16 +62,5 @@ public:
|
|||
BitMap();
|
||||
};
|
||||
|
||||
class ResourceFormatLoaderBitMap : public ResourceFormatLoader {
|
||||
|
||||
public:
|
||||
|
||||
virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
|
||||
virtual void get_recognized_extensions(List<String> *p_extensions) const;
|
||||
virtual bool handles_type(const String& p_type) const;
|
||||
virtual String get_resource_type(const String &p_path) const;
|
||||
|
||||
ResourceFormatLoaderBitMap();
|
||||
};
|
||||
|
||||
#endif // BIT_MASK_H
|
||||
|
|
|
@ -5953,6 +5953,7 @@ EditorNode::EditorNode() {
|
|||
resource_preview->add_preview_generator( Ref<EditorScriptPreviewPlugin>( memnew(EditorScriptPreviewPlugin )));
|
||||
resource_preview->add_preview_generator( Ref<EditorSamplePreviewPlugin>( memnew(EditorSamplePreviewPlugin )));
|
||||
resource_preview->add_preview_generator( Ref<EditorMeshPreviewPlugin>( memnew(EditorMeshPreviewPlugin )));
|
||||
resource_preview->add_preview_generator( Ref<EditorBitmapPreviewPlugin>( memnew(EditorBitmapPreviewPlugin )));
|
||||
|
||||
circle_step_msec=OS::get_singleton()->get_ticks_msec();
|
||||
circle_step_frame=OS::get_singleton()->get_frames_drawn();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "scene/resources/material.h"
|
||||
#include "scene/resources/sample.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
#include "scene/resources/bit_mask.h"
|
||||
|
||||
bool EditorTexturePreviewPlugin::handles(const String& p_type) const {
|
||||
|
||||
|
@ -56,6 +57,81 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES& p_from) {
|
|||
EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool EditorBitmapPreviewPlugin::handles(const String& p_type) const {
|
||||
|
||||
return ObjectTypeDB::is_type(p_type,"BitMap");
|
||||
}
|
||||
|
||||
Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES& p_from) {
|
||||
|
||||
Ref<BitMap> bm =p_from;
|
||||
|
||||
if (bm->get_size()==Size2()) {
|
||||
return Ref<Texture>();
|
||||
}
|
||||
|
||||
DVector<uint8_t> data;
|
||||
|
||||
data.resize(bm->get_size().width*bm->get_size().height);
|
||||
|
||||
{
|
||||
DVector<uint8_t>::Write w=data.write();
|
||||
|
||||
for(int i=0;i<bm->get_size().width;i++) {
|
||||
for(int j=0;j<bm->get_size().height;j++) {
|
||||
if (bm->get_bit(Point2i(i,j))) {
|
||||
w[j*bm->get_size().width+i]=255;
|
||||
} else {
|
||||
w[j*bm->get_size().width+i]=0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Image img(bm->get_size().width,bm->get_size().height,0,Image::FORMAT_GRAYSCALE,data);
|
||||
|
||||
int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
|
||||
if (img.is_compressed()) {
|
||||
if (img.decompress()!=OK)
|
||||
return Ref<Texture>();
|
||||
} else if (img.get_format()!=Image::FORMAT_RGB && img.get_format()!=Image::FORMAT_RGBA) {
|
||||
img.convert(Image::FORMAT_RGBA);
|
||||
}
|
||||
|
||||
int width,height;
|
||||
if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
|
||||
|
||||
width=thumbnail_size;
|
||||
height = img.get_height() * thumbnail_size / img.get_width();
|
||||
} else if (img.get_height() > thumbnail_size && img.get_height() >= img.get_width()) {
|
||||
|
||||
height=thumbnail_size;
|
||||
width = img.get_width() * thumbnail_size / img.get_height();
|
||||
} else {
|
||||
|
||||
width=img.get_width();
|
||||
height=img.get_height();
|
||||
}
|
||||
|
||||
img.resize(width,height);
|
||||
|
||||
Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
|
||||
|
||||
ptex->create_from_image(img,0);
|
||||
return ptex;
|
||||
|
||||
}
|
||||
|
||||
EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -13,6 +13,17 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class EditorBitmapPreviewPlugin : public EditorResourcePreviewGenerator {
|
||||
public:
|
||||
|
||||
virtual bool handles(const String& p_type) const;
|
||||
virtual Ref<Texture> generate(const RES& p_from);
|
||||
|
||||
EditorBitmapPreviewPlugin();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator {
|
||||
|
||||
Ref<Texture> _gen_from_imd(Ref<ResourceImportMetadata> p_imd);
|
||||
|
|
Loading…
Reference in New Issue