Пример #1
0
int IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field)
{
	ImMetaData *p;

	if (!img)
		return (0);

	if (!img->metadata)
		return (IMB_metadata_add_field (img, key, field));

	p = img->metadata;
	while (p) {
		if (!strcmp (key, p->key)) {
			MEM_freeN (p->value);
			p->value = BLI_strdup (field);
			return (1);
		}
		p = p->next;
	}

	return (IMB_metadata_add_field (img, key, field));
}
Пример #2
0
ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
	struct ImBuf *ibuf = NULL;
	png_structp png_ptr;
	png_infop info_ptr;
	unsigned char *pixels = NULL;
	unsigned short *pixels16 = NULL;
	png_bytepp row_pointers = NULL;
	png_uint_32 width, height;
	int bit_depth, color_type;
	PNGReadStruct ps;

	unsigned char *from, *to;
	unsigned short *from16;
	float *to_float;
	int i, bytesperpixel;

	if (imb_is_a_png(mem) == 0) return(NULL);

	/* both 8 and 16 bit PNGs are default to standard byte colorspace */
	colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
	                                 NULL, NULL, NULL);
	if (png_ptr == NULL) {
		printf("Cannot png_create_read_struct\n");
		return NULL;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, 
		                        (png_infopp)NULL);
		printf("Cannot png_create_info_struct\n");
		return NULL;
	}

	ps.size = size; /* XXX, 4gig limit! */
	ps.data = mem;
	ps.seek = 0;

	png_set_read_fn(png_ptr, (void *) &ps, ReadData);

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		if (pixels) MEM_freeN(pixels);
		if (pixels16) MEM_freeN(pixels16);
		if (row_pointers) MEM_freeN(row_pointers);
		if (ibuf) IMB_freeImBuf(ibuf);
		return NULL;
	}

	// png_set_sig_bytes(png_ptr, 8);

	png_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 
	             &color_type, NULL, NULL, NULL);

	bytesperpixel = png_get_channels(png_ptr, info_ptr);

	switch (color_type) {
		case PNG_COLOR_TYPE_RGB:
		case PNG_COLOR_TYPE_RGB_ALPHA:
			break;
		case PNG_COLOR_TYPE_PALETTE:
			png_set_palette_to_rgb(png_ptr);
			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
				bytesperpixel = 4;
			}
			else {
				bytesperpixel = 3;
			}
			break;
		case PNG_COLOR_TYPE_GRAY:
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			if (bit_depth < 8) {
				png_set_expand(png_ptr);
				bit_depth = 8;
			}
			break;
		default:
			printf("PNG format not supported\n");
			longjmp(png_jmpbuf(png_ptr), 1);
	}
	
	ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0);

	if (ibuf) {
		ibuf->ftype = PNG;
		if (bit_depth == 16)
			ibuf->ftype |= PNG_16BIT;

		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
			int unit_type;
			png_uint_32 xres, yres;

			if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type))
				if (unit_type == PNG_RESOLUTION_METER) {
					ibuf->ppm[0] = xres;
					ibuf->ppm[1] = yres;
				}
		}
	}
	else {
		printf("Couldn't allocate memory for PNG image\n");
	}

	if (ibuf && ((flags & IB_test) == 0)) {
		if (bit_depth == 16) {
			imb_addrectfloatImBuf(ibuf);
			png_set_swap(png_ptr);

			pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(png_uint_16), "pixels");
			if (pixels16 == NULL) {
				printf("Cannot allocate pixels array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* allocate memory for an array of row-pointers */
			row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_uint_16p), "row_pointers");
			if (row_pointers == NULL) {
				printf("Cannot allocate row-pointers array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* set the individual row-pointers to point at the correct offsets */
			for (i = 0; i < ibuf->y; i++) {
				row_pointers[ibuf->y - 1 - i] = (png_bytep)
				                                ((png_uint_16 *)pixels16 + (i * ibuf->x) * bytesperpixel);
			}

			png_read_image(png_ptr, row_pointers);

			/* copy image data */

			to_float = ibuf->rect_float;
			from16 = pixels16;

			switch (bytesperpixel) {
				case 4:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = from16[0] / 65535.0;
						to_float[1] = from16[1] / 65535.0;
						to_float[2] = from16[2] / 65535.0;
						to_float[3] = from16[3] / 65535.0;
						to_float += 4; from16 += 4;
					}
					break;
				case 3:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = from16[0] / 65535.0;
						to_float[1] = from16[1] / 65535.0;
						to_float[2] = from16[2] / 65535.0;
						to_float[3] = 1.0;
						to_float += 4; from16 += 3;
					}
					break;
				case 2:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
						to_float[3] = from16[1] / 65535.0;
						to_float += 4; from16 += 2;
					}
					break;
				case 1:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
						to_float[3] = 1.0;
						to_float += 4; from16++;
					}
					break;
			}
		}
		else {
			imb_addrectImBuf(ibuf);

			pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
			if (pixels == NULL) {
				printf("Cannot allocate pixels array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* allocate memory for an array of row-pointers */
			row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
			if (row_pointers == NULL) {
				printf("Cannot allocate row-pointers array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* set the individual row-pointers to point at the correct offsets */
			for (i = 0; i < ibuf->y; i++) {
				row_pointers[ibuf->y - 1 - i] = (png_bytep)
				                                ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
			}

			png_read_image(png_ptr, row_pointers);

			/* copy image data */

			to = (unsigned char *) ibuf->rect;
			from = pixels;

			switch (bytesperpixel) {
				case 4:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = from[0];
						to[1] = from[1];
						to[2] = from[2];
						to[3] = from[3];
						to += 4; from += 4;
					}
					break;
				case 3:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = from[0];
						to[1] = from[1];
						to[2] = from[2];
						to[3] = 0xff;
						to += 4; from += 3;
					}
					break;
				case 2:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = to[1] = to[2] = from[0];
						to[3] = from[1];
						to += 4; from += 2;
					}
					break;
				case 1:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = to[1] = to[2] = from[0];
						to[3] = 0xff;
						to += 4; from++;
					}
					break;
			}
		}

		if (flags & IB_metadata) {
			png_text *text_chunks;
			int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL);
			for (i = 0; i < count; i++) {
				IMB_metadata_add_field(ibuf, text_chunks[i].key, text_chunks[i].text);
				ibuf->flags |= IB_metadata;
			}
		}

		png_read_end(png_ptr, info_ptr);
	}

	/* clean up */
	if (pixels)
		MEM_freeN(pixels);
	if (pixels16)
		MEM_freeN(pixels16);
	if (row_pointers)
		MEM_freeN(row_pointers);
	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

	return(ibuf);
}
Пример #3
0
static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int flags)
{
    JSAMPARRAY row_pointer;
    JSAMPLE * buffer = NULL;
    int row_stride;
    int x, y, depth, r, g, b, k;
    struct ImBuf * ibuf = NULL;
    uchar * rect;
    jpeg_saved_marker_ptr marker;
    char *str, *key, *value;

    /* install own app1 handler */
    ibuf_ftype = 0;
    jpeg_set_marker_processor(cinfo, 0xe1, handle_app1);
    cinfo->dct_method = JDCT_FLOAT;
    jpeg_save_markers(cinfo, JPEG_COM, 0xffff);

    if (jpeg_read_header(cinfo, FALSE) == JPEG_HEADER_OK) {
        x = cinfo->image_width;
        y = cinfo->image_height;
        depth = cinfo->num_components;

        if (cinfo->jpeg_color_space == JCS_YCCK) cinfo->out_color_space = JCS_CMYK;

        jpeg_start_decompress(cinfo);

        if (ibuf_ftype == 0) {
            ibuf_ftype = JPG_STD;
            if (cinfo->max_v_samp_factor == 1) {
                if (cinfo->max_h_samp_factor == 1) ibuf_ftype = JPG_MAX;
                else ibuf_ftype = JPG_VID;
            }
        }

        if (flags & IB_test) {
            jpeg_abort_decompress(cinfo);
            ibuf = IMB_allocImBuf(x, y, 8 * depth, 0);
        }
        else if ((ibuf = IMB_allocImBuf(x, y, 8 * depth, IB_rect)) == NULL) {
            jpeg_abort_decompress(cinfo);
        }
        else {
            row_stride = cinfo->output_width * depth;

            row_pointer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1);

            for (y = ibuf->y - 1; y >= 0; y--) {
                jpeg_read_scanlines(cinfo, row_pointer, 1);
                rect = (uchar *) (ibuf->rect + y * ibuf->x);
                buffer = row_pointer[0];

                switch(depth) {
                case 1:
                    for (x=ibuf->x; x >0; x--) {
                        rect[3] = 255;
                        rect[0] = rect[1] = rect[2] = *buffer++;
                        rect += 4;
                    }
                    break;
                case 3:
                    for (x=ibuf->x; x >0; x--) {
                        rect[3] = 255;
                        rect[0] = *buffer++;
                        rect[1] = *buffer++;
                        rect[2] = *buffer++;
                        rect += 4;
                    }
                    break;
                case 4:
                    for (x=ibuf->x; x >0; x--) {
                        r = *buffer++;
                        g = *buffer++;
                        b = *buffer++;
                        k = *buffer++;

                        k = 255 - k;
                        r -= k;
                        if (r & 0xffffff00) {
                            if (r < 0) r = 0;
                            else r = 255;
                        }
                        g -= k;
                        if (g & 0xffffff00) {
                            if (g < 0) g = 0;
                            else g = 255;
                        }
                        b -= k;
                        if (b & 0xffffff00) {
                            if (b < 0) b = 0;
                            else b = 255;
                        }

                        rect[3] = 255 - k;
                        rect[2] = b;
                        rect[1] = g;
                        rect[0] = r;
                        rect += 4;
                    }
                }
            }

            marker= cinfo->marker_list;
            while(marker) {
                if(marker->marker != JPEG_COM)
                    goto next_stamp_marker;

                /*
                 * Because JPEG format don't support the
                 * pair "key/value" like PNG, we store the
                 * stampinfo in a single "encode" string:
                 *	"Blender:key:value"
                 *
                 * That is why we need split it to the
                 * common key/value here.
                 */
                if(strncmp((char *) marker->data, "Blender", 7)) {
                    /*
                     * Maybe the file have text that
                     * we don't know "what it's", in that
                     * case we keep the text (with a
                     * key "None").
                     * This is only for don't "lose"
                     * the information when we write
                     * it back to disk.
                     */
                    IMB_metadata_add_field(ibuf, "None", (char *) marker->data);
                    ibuf->flags |= IB_metadata;
                    goto next_stamp_marker;
                }

                str = BLI_strdup ((char *) marker->data);
                key = strchr (str, ':');
                /*
                 * A little paranoid, but the file maybe
                 * is broken... and a "extra" check is better
                 * that a segfaul ;)
                 */
                if (!key) {
                    MEM_freeN(str);
                    goto next_stamp_marker;
                }

                key++;
                value = strchr (key, ':');
                if (!value) {
                    MEM_freeN(str);
                    goto next_stamp_marker;
                }

                *value = '\0'; /* need finish the key string */
                value++;
                IMB_metadata_add_field(ibuf, key, value);
                ibuf->flags |= IB_metadata;
                MEM_freeN(str);
next_stamp_marker:
                marker= marker->next;
            }

            jpeg_finish_decompress(cinfo);
        }

        jpeg_destroy((j_common_ptr) cinfo);
        if(ibuf) {
            ibuf->ftype = ibuf_ftype;
            ibuf->profile = IB_PROFILE_SRGB;
        }
    }

    return(ibuf);
}