📄 image_in.cpp
字号:
scan->next_x_tnum = 0; } assert((scan->width-scan->accessed_samples) >= line.get_width()); if (line.get_buf32() != NULL) { if (line.is_absolute()) convert_words_to_ints(scan->buf+sample_bytes*scan->accessed_samples, line.get_buf32(),line.get_width(), precision,is_signed,sample_bytes); else convert_words_to_floats(scan->buf+sample_bytes*scan->accessed_samples, line.get_buf32(),line.get_width(), precision,is_signed,sample_bytes); } else { if (line.is_absolute()) convert_words_to_shorts(scan->buf+sample_bytes*scan->accessed_samples, line.get_buf16(),line.get_width(), precision,is_signed,sample_bytes); else convert_words_to_fixpoint(scan->buf+sample_bytes*scan->accessed_samples, line.get_buf16(),line.get_width(), precision,is_signed,sample_bytes); } scan->next_x_tnum++; scan->accessed_samples += line.get_width(); if (scan->accessed_samples == scan->width) { // Send empty line to free list. assert(scan == incomplete_lines); incomplete_lines = scan->next; scan->next = free_lines; free_lines = scan; } return true;}/* ========================================================================= *//* bmp_in *//* ========================================================================= *//*****************************************************************************//* bmp_in::bmp_in *//*****************************************************************************/bmp_in::bmp_in(char const *fname, siz_params *siz, int &next_comp_idx, bool &vflip, kdu_rgb8_palette *palette){ int n; if ((in = fopen(fname,"rb")) == NULL) { kdu_error e; e << "Unable to open input image file, \"" << fname <<"\"."; } kdu_byte magic[14]; bmp_header header; fread(magic,1,14,in); if ((magic[0] != 'B') || (magic[1] != 'M') || (fread(&header,1,40,in) != 40)) { kdu_error e; e << "BMP image file must start with the magic string, " "\"BM\", and continue with a header whose total size is at least 54 " "bytes."; } from_little_endian((kdu_int32 *) &header,10); cols = header.width; rows = header.height; if (rows < 0) rows = -rows; else vflip = true; bytes = nibbles = bits = expand_palette = false; int precision = 8; if (header.bit_count == 24) num_components = 3; else if (header.bit_count == 8) { num_components = 1; bytes = true; } else if (header.bit_count == 4) { num_components = 1; nibbles = true; precision = 4; } else if (header.bit_count == 1) { num_components = 1; bits = true; precision = 1; } else { kdu_error e; e << "We currently support only 1-, 4-, 8- and 24-bit BMP files."; } int header_size = 54 + ((num_components==1)?(4<<precision):0); int offset = magic[13]; offset <<= 8; offset += magic[12]; offset <<= 8; offset += magic[11]; offset <<= 8; offset += magic[10]; if (offset < header_size) { kdu_error e; e << "Invalid sample data offset field specified in BMP " "file header!"; } if (num_components == 1) { fread(map,1,4<<precision,in); if (bytes) { for (n=0; n < 256; n++) if ((map[4*n] != n) || (map[4*n+1] != n) || (map[4*n+2] != n)) break; if (n == 256) bytes = false; // No need to use palette } } if (bytes || nibbles || bits) { if ((palette == NULL) || palette->exists()) { expand_palette = true; // Need to expand the palette here. precision = 8; for (n=0; n < 256; n++) if ((map[4*n] != map[4*n+1]) || (map[4*n] != map[4*n+2])) break; // Not a monochrome source. num_components = (n==256)?1:3; } else { // Set up the colour palette. palette->input_bits = precision; palette->output_bits = 8; palette->source_component = next_comp_idx; for (n=0; n < (1<<precision); n++) { palette->blue[n] = map[4*n+0]; palette->green[n] = map[4*n+1]; palette->red[n] = map[4*n+2]; } for (n=0; n < (1<<precision); n++) map[n] = n; // Set identity permutation for now. if (nibbles || bytes) palette->rearrange(map); // Try to find a better permutation. } } if (offset > header_size) fseek(in,offset-header_size,SEEK_CUR); first_comp_idx = next_comp_idx; for (n=0; n < num_components; n++) { next_comp_idx++; siz->set(Sdims,first_comp_idx+n,0,rows); siz->set(Sdims,first_comp_idx+n,1,cols); siz->set(Ssigned,first_comp_idx+n,0,false); siz->set(Sprecision,first_comp_idx+n,0,precision); } incomplete_lines = NULL; free_lines = NULL; num_unread_rows = rows; if (bytes) line_bytes = cols; else if (nibbles) line_bytes = (cols+1)>>1; else if (bits) line_bytes = (cols+7)>>3; else line_bytes = cols*num_components; line_bytes += (-line_bytes) & 3; // Pad to a multiple of 4 bytes.}/*****************************************************************************//* bmp_in::~bmp_in *//*****************************************************************************/bmp_in::~bmp_in(){ if ((num_unread_rows > 0) || (incomplete_lines != NULL)) { kdu_warning w; w << "Not all rows of image components " << first_comp_idx << " through " << first_comp_idx+num_components-1 << " were consumed!"; } image_line_buf *tmp; while ((tmp=incomplete_lines) != NULL) { incomplete_lines = tmp->next; delete tmp; } while ((tmp=free_lines) != NULL) { free_lines = tmp->next; delete tmp; } fclose(in);}/*****************************************************************************//* bmp_in::get *//*****************************************************************************/bool bmp_in::get(int comp_idx, kdu_line_buf &line, int x_tnum){ int idx = comp_idx - this->first_comp_idx; assert((idx >= 0) && (idx < num_components)); x_tnum = x_tnum*num_components+idx; image_line_buf *scan, *prev=NULL; for (scan=incomplete_lines; scan != NULL; prev=scan, scan=scan->next) { assert(scan->next_x_tnum >= x_tnum); if (scan->next_x_tnum == x_tnum) break; } if (scan == NULL) { // Need to read a new image line. assert(x_tnum == 0); // Must consume in very specific order. if (num_unread_rows == 0) return false; if ((scan = free_lines) == NULL) scan = new image_line_buf(cols+7,num_components); // Big enough for padding and expanding bits to bytes free_lines = scan->next; if (prev == NULL) incomplete_lines = scan; else prev->next = scan; if (fread(scan->buf,1,(size_t) line_bytes,in) != (size_t) line_bytes) { kdu_error e; e << "Image file for components " << first_comp_idx << " through " << first_comp_idx+num_components-1 << " terminated prematurely!"; } num_unread_rows--; scan->accessed_samples = 0; scan->next_x_tnum = 0; if (bytes) map_palette_index_bytes(scan->buf,line.is_absolute()); else if (nibbles) map_palette_index_nibbles(scan->buf,line.is_absolute()); else if (bits) map_palette_index_bits(scan->buf,line.is_absolute()); } assert((cols-scan->accessed_samples) >= line.get_width()); int comp_offset = (num_components==3)?(2-idx):0; kdu_byte *sp = scan->buf+num_components*scan->accessed_samples + comp_offset; int n=line.get_width(); if (line.get_buf32() != NULL) { kdu_sample32 *dp = line.get_buf32(); if (line.is_absolute()) { // 32-bit absolute integers kdu_int32 offset = 128; if ((num_components == 1) && nibbles) offset = 8; if ((num_components == 1) && bits) offset = 1; for (; n > 0; n--, sp+=num_components, dp++) dp->ival = ((kdu_int32)(*sp)) - offset; } else { // true 32-bit floats for (; n > 0; n--, sp+=num_components, dp++) dp->fval = (((float)(*sp)) / 256.0F) - 0.5F; } } else { kdu_sample16 *dp = line.get_buf16(); if (line.is_absolute()) { // 16-bit absolute integers kdu_int16 offset = 128; if ((num_components == 1) && nibbles) offset = 8; if ((num_components == 1) && bits) offset = 1; for (; n > 0; n--, sp+=num_components, dp++) dp->ival = ((kdu_int16)(*sp)) - offset; } else { // 16-bit normalized representation. for (; n > 0; n--, sp+=num_components, dp++) dp->ival = (((kdu_int16)(*sp)) - 128) << (KDU_FIX_POINT-8); } } scan->next_x_tnum++; if (idx == (num_components-1)) scan->accessed_samples += line.get_width(); if (scan->accessed_samples == cols) { // Send empty line to free list. assert(scan == incomplete_lines); incomplete_lines = scan->next; scan->next = free_lines; free_lines = scan; } return true;}/*****************************************************************************//* bmp_in::map_palette_index_bytes *//*****************************************************************************/void bmp_in::map_palette_index_bytes(kdu_byte *buf, bool absolute){ int n = cols; if (num_components == 3) { // Expand single component through palette assert(expand_palette); kdu_byte *sp = buf + n; kdu_byte *dp = buf + (3*n); kdu_byte *mp; for (; n > 0; n--) { mp = map + (((int) *(--sp))<<2); *(--dp) = mp[2]; *(--dp) = mp[1]; *(--dp) = mp[0]; } } else if (expand_palette) { assert(num_components == 1); kdu_byte *sp = buf + n; kdu_byte *dp = buf + n; for (; n > 0; n--) *(--dp) = map[((int) *(--sp))<<2]; } else { // Apply optimized permutation map to the palette indices assert(num_components == 1); for (; n > 0; n--, buf++) *buf = map[*buf]; }}/*****************************************************************************//* bmp_in::map_palette_index_nibbles *//*****************************************************************************/void bmp_in::map_palette_index_nibbles(kdu_byte *buf, bool absolute){ int n = (cols+1)>>1; if (num_components == 3) { // Expand single component through palette assert(expand_palette); kdu_byte *sp = buf + n; kdu_byte *dp = buf + (6*n); kdu_byte *mp; kdu_uint32 val; for (; n > 0; n--) { val = *(--sp); mp = map + ((val & 0x0F)<<2); *(--dp) = mp[2]; *(--dp) = mp[1]; *(--dp) = mp[0]; val >>= 4; mp = map + ((val & 0x0F)<<2); *(--dp) = mp[2]; *(--dp) = mp[1]; *(--dp) = mp[0]; } } else if (expand_palette) { assert(num_components == 1); kdu_byte *sp = buf + n; kdu_byte *dp = buf + (2*n); kdu_uint32 val; for (; n > 0; n--) { val = *(--sp); *(--dp) = map[(val & 0x0F) << 2]; val >>= 4; *(--dp) = map[(val & 0x0F) << 2]; } } else { // Apply optimized permutation map to the palette indices assert(num_components == 1); kdu_byte *sp = buf + n; kdu_byte *dp = buf + (2*n); kdu_byte val; if (absolute) { // Map nibbles and store in least significant 4 bits of byte for (; n > 0; n--) { val = *(--sp); *(--dp) = map[val & 0x0F]; val >>= 4; *(--dp) = map[val & 0x0F]; } } else { // Map nibbles and store in most significant 4 bits of byte for (; n > 0; n--) { val = *(--sp); *(--dp) = map[val & 0x0F]<<4; val >>= 4; *(--dp) = map[val & 0x0F]<<4; } } }}/*****************************************************************************//* bmp_in::map_palette_index_bits *//*****************************************************************************/void bmp_in::map_palette_index_bits(kdu_byte *buf, bool absolute){ int b, n = (cols+7)>>3; if (num_components == 3) { // Expand single component through palette assert(expand_palette); kdu_byte *sp = buf + n; kdu_byte *dp = buf + (24*n); kdu_byte *mp; kdu_uint32 val; for (; n > 0; n--) { val = *(--sp); for (b=8; b > 0; b--, val>>=1) { mp = map + ((val & 1)<<2); *(--dp) = mp[2]; *(--dp) = mp[1]; *(--dp) = mp[0]; } } } else if (expand_palette) { assert(num_components == 1); kdu_byte *sp = buf + n; kdu_byte *dp = buf + (8*n); kdu_uint32 val; for (; n > 0; n--) { val = *(--sp); for (b=8; b > 0; b--, val>>=1) *(--dp) = map[(val & 1)<<2]; } } else { // Apply optimized permutation map to the palette indices assert(num_components == 1); kdu_byte *sp = buf + n; kdu_byte *dp = buf + (8*n); kdu_byte val; if (absolute) { // Store bits in LSB's of bytes for (; n > 0; n--) { val = *(--sp); for (b=8; b > 0; b--, val>>=1) *(--dp) = val&1; } } else { // Store bits in MSB's of bytes for (; n > 0; n--) { val = *(--sp); for (b=8; b > 0; b--, val>>=1) *(--dp) = (val&1)<<7; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -